Java java.lang 包详解
java.lang包 是 Java 语言的核心包,它包含了构成 Java 语言基础的类和接口。这个包是如此重要,以至于在编写 Java 代码时,其中的所有类和接口都会被自动导入 (implicitly imported),开发者无需使用import语句。java.lang包定义了对象的根基、基本数据类型的封装、字符串处理、系统操作、线程管理以及异常处理等核心功能。
核心思想:java.lang 包定义了 Java 语言最基础、最核心的构建块,是所有 Java 程序的基石,提供对象模型、基本类型支持、字符串、并发、系统交互和异常处理等基础能力。
一、java.lang 包的重要性
java.lang 包是 Java 编程的起点和核心。其重要性体现在:
- 自动导入:无需
import java.lang.*,其中的所有类和接口都可直接使用。 - 对象模型的基础:
Object类是所有类的父类。 - 基本数据类型的封装:提供了对应八种基本数据类型的包装类。
- 字符串处理:提供了
String,StringBuffer,StringBuilder等核心字符串操作类。 - 运行时环境交互:
System,Runtime,Process等类允许程序与操作系统和 JVM 进行交互。 - 并发编程基础:
Thread,Runnable等为多线程编程提供了基础。 - 异常处理机制:
Throwable及其子类构成了 Java 强大的异常处理体系。 - 反射机制入口:
Class类是 Java 反射机制的基石。
二、java.lang 包中的核心类和接口
2.1 Object 类
- 定义:
Object是所有 Java 类的最终父类。每个类都直接或间接地继承自Object类。 - 作用:提供了所有对象都应具备的基本行为,是 Java 对象模型的根基。
- 常用方法:
boolean equals(Object obj):比较两个对象是否相等。默认实现比较内存地址 (即==运算符)。通常需要根据业务逻辑重写。int hashCode():返回对象的哈希码。与equals()约定:如果两个对象equals返回true,则它们的hashCode也必须相等。String toString():返回对象的字符串表示。默认返回类名@哈希码的十六进制。建议重写以提供有意义的字符串描述。Class<?> getClass():返回此Object的运行时类。这是反射的入口点。void wait(),void wait(long timeout),void wait(long timeout, int nanos):在当前线程上等待,直到另一个线程调用此对象的notify()或notifyAll()方法,或超时发生。必须在synchronized块内调用。void notify():唤醒在此对象监视器上等待的单个线程。必须在synchronized块内调用。void notifyAll():唤醒在此对象监视器上等待的所有线程。必须在synchronized块内调用。protected Object clone():创建并返回此对象的副本。需要类实现Cloneable接口。protected void finalize():当垃圾收集器确定不再有对该对象的引用时,由垃圾收集器调用。不推荐使用,因为其执行时机不确定且可能引入性能问题。
示例:Object 方法的重写
1 | import java.util.Objects; |
2.2 Class 类
- 定义:
Class类的实例代表正在运行的 Java 应用程序中的类和接口。每个加载到 JVM 中的类都有一个对应的Class对象。 - 作用:是 Java 反射 (Reflection) 机制的入口。通过
Class对象,可以在运行时获取类的构造器、方法、字段等信息,并动态创建对象、调用方法。 - 获取
Class对象的方式:Object.getClass():对象实例.getClass()。类名.class:MyClass.class。Class.forName(String className):Class.forName("com.example.MyClass"),需要处理ClassNotFoundException。
示例:Class 类的使用
1 | import java.lang.reflect.Method; |
2.3 String, StringBuffer, StringBuilder 类
这三个类都用于处理字符串,但它们在可变性、线程安全性和性能方面有所不同。
String:- 不可变 (Immutable):一旦创建,其内容不能被改变。所有对
String对象的修改操作 (如concat(),substring()) 都会生成一个新的String对象。 - 线程安全:由于不可变性,
String是天然线程安全的。 - 性能:频繁修改字符串会创建大量新对象,导致性能开销和 GC 压力。
- 字符串常量池:字面量字符串 (
"abc") 会被存储在字符串常量池中,以实现内存共享。
- 不可变 (Immutable):一旦创建,其内容不能被改变。所有对
StringBuffer:- 可变 (Mutable):提供了
append(),insert(),delete()等方法来修改其内容,而无需创建新对象。 - 线程安全:所有公共方法都使用了
synchronized关键字进行同步,因此是线程安全的。 - 性能:在多线程环境下,性能开销略高,但在需要频繁修改字符串的场景下优于
String。
- 可变 (Mutable):提供了
StringBuilder:- 可变 (Mutable):与
StringBuffer类似,提供可变字符串操作。 - 非线程安全:方法没有同步,因此在单线程环境下性能优于
StringBuffer。 - 性能:在单线程环境下需要频繁修改字符串时,是最佳选择。
- 可变 (Mutable):与
选择建议:
String:适用于字符串内容不会或很少变化的场景。StringBuilder:适用于单线程环境下,需要频繁对字符串进行修改的场景。StringBuffer:适用于多线程环境下,需要频繁对字符串进行修改的场景。
示例:字符串操作
1 | public class StringBuildersDemo { |
2.4 包装类 (Wrapper Classes)
Java 为八种基本数据类型提供了对应的包装类,用于将基本数据类型封装成对象,以便进行更复杂的操作,或在需要对象的地方使用 (如集合类)。
| 基本数据类型 | 包装类 |
|---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
boolean |
Boolean |
char |
Character |
void |
Void (特殊,无实例) |
- 作用:
- 作为基本数据类型和对象之间的桥梁。
- 在集合框架 (
ArrayList,HashMap等) 中存储基本数据类型的值。 - 提供了处理基本数据类型值的实用方法 (如字符串转换、解析)。
- 自动装箱 (Autoboxing) 与自动拆箱 (Unboxing):
- Java 5 引入的特性,允许基本数据类型和其对应的包装类之间自动转换。
- 自动装箱:将基本数据类型自动转换为其包装类对象 (例如
int转Integer)。 - 自动拆箱:将包装类对象自动转换为其基本数据类型 (例如
Integer转int)。
示例:包装类与自动装箱/拆箱
1 | public class WrapperClassDemo { |
2.5 System 类
- 定义:一个提供访问系统资源的
final静态工具类。 - 作用:提供了标准输入输出流、加载库、复制数组、获取系统时间、退出 JVM 等静态方法和字段。
- 常用成员:
static InputStream in:标准输入流 (通常是键盘)。static PrintStream out:标准输出流 (通常是控制台)。static PrintStream err:标准错误输出流 (通常是控制台)。static long currentTimeMillis():返回当前时间的毫秒表示。static long nanoTime():返回当前时间的纳秒表示 (用于精确测量时间间隔)。static void exit(int status):终止当前正在运行的 Java 虚拟机。status为非零表示异常退出。static Properties getProperties():获取所有系统属性。static String getProperty(String key):获取指定键的系统属性值。static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):高效地复制数组。
示例:System 类的使用
1 | import java.util.Properties; |
2.6 Thread 类与 Runnable 接口
Thread类:- 定义:代表程序中的一个执行线程。
- 作用:可以直接创建
Thread对象来创建线程,并重写其run()方法来定义线程的执行逻辑。
Runnable接口:- 定义:一个函数式接口,包含一个
void run()方法。 - 作用:用于定义线程的执行逻辑。通过实现
Runnable接口,可以将线程的执行逻辑与线程对象本身解耦,更灵活地创建线程。
- 定义:一个函数式接口,包含一个
创建线程的两种方式:
- 继承
Thread类:1
2
3
4
5
6
7class MyThread extends Thread {
public void run() {
System.out.println("Thread extending Thread is running.");
}
}
// 使用:new MyThread().start(); - 实现
Runnable接口 (推荐,更灵活,可避免单继承限制):1
2
3
4
5
6
7class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread implementing Runnable is running.");
}
}
// 使用:new Thread(new MyRunnable()).start();
示例:线程创建
1 | public class ThreadDemo { |
2.7 Throwable 类及其子类
- 定义:
Throwable是所有错误 (Error) 和异常 (Exception) 的超类。只有当对象是Throwable的实例 (或子类实例) 时,才能通过throw语句抛出。 - 作用:构成了 Java 强大的异常处理机制,允许程序在运行时报告和处理错误。
Throwable 的子类层次结构:
graph LR
A[Throwable] --> B[Error]
A --> C[Exception]
C --> D[RuntimeException]
C --> E[IOException]
C --> F[SQLException]
D --> G[NullPointerException]
D --> H[ArrayIndexOutOfBoundsException]
D --> I[IllegalArgumentException]
B --> J[OutOfMemoryError]
B --> K[StackOverflowError]
Error:- 定义:表示应用程序无法处理的严重问题。通常是 JVM 内部错误或资源耗尽等。
- 特点:非受检异常 (Unchecked Exception)。程序不应尝试捕获或处理
Error。 - 常见示例:
OutOfMemoryError,StackOverflowError。
Exception:- 定义:表示应用程序可以捕获和处理的异常情况。
- 特点:
- 受检异常 (Checked Exception):编译器会强制要求捕获 (
try-catch) 或声明抛出 (throws)。例如IOException,SQLException。 - 非受检异常 (Unchecked Exception):继承自
RuntimeException的异常。编译器不会强制处理。 - 常见示例:
NullPointerException,ArrayIndexOutOfBoundsException,IllegalArgumentException(非受检);IOException(受检)。
- 受检异常 (Checked Exception):编译器会强制要求捕获 (
示例:异常处理
1 | import java.io.FileInputStream; |
2.8 其他重要类和接口
Enum:所有枚举类型的公共基类。Math/StrictMath:提供了各种数学函数,如abs,sqrt,pow,random等。StrictMath保证跨平台结果一致性。Comparable接口:定义了对象的自然排序方式,包含int compareTo(T o)方法。CharSequence接口:表示一个字符序列,String,StringBuffer,StringBuilder都实现了此接口。Runtime类:每个 Java 应用程序都有一个Runtime类实例,允许应用程序与运行它的环境进行交互,如执行外部命令 (exec())。Process类:Runtime.exec()方法返回一个Process对象,代表一个外部进程。Void类:一个不可实例化的占位符类,用于表示void类型,主要用于反射机制。- 核心注解:
@Override(表明方法重写)、@Deprecated(标记不推荐使用)、@SuppressWarnings(抑制编译器警告)。
三、总结
java.lang 包是 Java 语言的基石,它提供了构建任何 Java 应用程序所必需的最基本和最核心的功能。从 Object 类奠定的面向对象基础,到 String 提供的强大字符串处理,再到 Thread 和 Throwable 带来的并发和健壮性,以及 System 和 Runtime 对系统资源的访问,理解 java.lang 包是深入学习 Java 的第一步,也是编写高质量、高效 Java 代码的关键。由于其重要性,JVM 会自动导入此包,使得这些核心类和接口始终触手可及。
