# API-语言基础类库 (Package java.lang
)
# 4.1 Object
类
# 4.1.1 基本信息
Package java.lang
public class Object
Object
类是所有类的父类。在 Java 中处于顶级父类的地位,是类层级结构的根类。任何类对象都可以用
Object
类的对象来接收。
# 4.1.2 重要方法
clone()
克隆一个对象。
当一个对象要被克隆时,它所对应的类必须实现
Cloneable
接口。克隆完成后会产生一个新的对象。新对象和原对象的地址不同,但属性值相同。
Cloneable
接口
其中没有任何属性和方法,仅用于标识此类产生的对象可以被克隆。
finalize()
通知
GC
回收当前对象。即使
GC
已经开始运行,也只回收当前对象而不回收其他对象。*
System.gc()
通知GC
回收所有可以回收的对象。→System
类
getClass()
获取对象的运行时类对象(如,后续可用于反射)。hashCode()
获取该对象的哈希码值,在一定范围内可以认为是唯一的。哈希码为一串 32 位的二进制数据。toString()
打印对象。实际调用对象本身的toString()
。equals(Object obj)
比较两个对象是否相等。默认比较对象的地址,但对于File
,String
,Date
和包装类来说,它们比较地是对象值。重写
equals()
当手动重写
equals()
时,思路为:判断地址是否一致(
if (this == obj)
)判断参数是否为空(
if (obj == null)
)判断类型是否一致(
if (this.getClass() != obj.getClass())
)判断属性值是否一致
hashCode()
与 euqals()
- 如果两个对象相等,则 hashcode 一定也是相同的
- 两个对象相等,对两个
equals()
方法返回true
- 两个对象有相同的 hashcode 值,它们也不一定是相等的
综上,如果一个类的 equals()
方法被覆盖过,则 hashCode()
方法也必须被覆盖。
# 4.2 System
类
# 4.2.1 基本信息
Package java.lang
public final class System
System
类提供了标准输入输出、错误输入输出和一些访问系统属性的方法。它是一个静态类,不能被继承,不能被实例化,所有方法都是静态方法。
# 4.2.2 重要方法
static void gc()
强制 Java 虚拟机启动垃圾回收机制,收集内存中所有不再被引用的对象所占用的内存空间。
static void exit(int status)
强制终止当前正在运行的 Java 虚拟机,并将参数
status
返回给系统。通常来讲,status
为 0 表示正常终止;非 0 表示异常终止。static long currentTimeMillis()
返回从 1970 年 1 月 1 日到当前系统时间的毫秒数。
关于System
类的属性
in
从键盘输入信息,只能按字节读取out
将信息标准输出到显示器(是PrintStream
类的对象,声明:static final PrintStream out
)err
将错误提示信息(使用红色字体)输出到显示器(是PrintStream
类的对象,声明:static final PrintStream err
)
*这三个属性都是字节流,见 I/O Stream.
# 4.3 异常
异常是一套处理和反馈问题的机制。
# 4.3.1 基本信息
Package java.lang
public class Throwable
Throwable
类是异常 (Exception) 和错误 (Error) 的父类。错误无法处理,而异常可以处理。
# 4.3.2 Exception
分类
编译时异常(或称已检查异常):编译期出现的异常,要求必须处理,抛出或者捕获。
如:CloneNotSupportedException
和ParseException
运行时异常(或称未检查异常):编译期不报错,但运行时出现。在编译期处理与否均可,往往非语法错误。
如:ArithmeticException
、ArrayIndexOutOfBoundException
、NullPointerException
、ClassCastException
和NumberFormatException
自定义异常:编程者通过继承某个异常类自己编写的异常。
关于异常处理
运行时异常可以随意抛出和捕获
编译时异常只能在抛出时捕获
关于异常捕获
使用多个
catch
来分别捕获不同的异常可以捕获一个父类异常,统一处理
在一个
catch
语句中,可以使用|
分割不同的异常来分组处理,避免了写多个catch
语句> Java SE 7.0当一个方法声明抛出父类异常时,处理中必须处理父类异常
在捕获异常时,需要先捕获子类异常再捕获父类异常
关于 finally
无论是否发生异常都会执行
# 4.3.3 Error
错误。不应试图捕获的严重问题。无法处理。
# 4.4 枚举
# 4.4.1 基本信息
Package java.lang
public abstract class Enum<E extends Enum<E>>
取值固定且能一一列举
枚举常量必须定义在首行,用
,
隔开,以;
结尾枚举类中允许定义属性和方法
枚举类构造函数默认且只能为私有
可以携带参数,在枚举后添加括号可以定义抽象方法,以匿名内部类的形式实现
switch(表达式)
表达式值新添Enum常量
# 4.5 String
类
# 4.5.1 基本信息
Package java.lang
public final class String
String
类是一个最终类,表示字符串。所有字符串都是
String
类的实例。字符串是常量,创建后不可更改,但可以被共享。
# 4.5.2 重要方法
char chatAt()
获取字符串指定下标字符。int length()
获取字符串长度。char[] toCharArray()
将字符串转化为字符数组。其他不改变原串的方法
方法 描述 备注 int compareTo(String another)
判断两个字符串大小,根据返回值正负来确定 String concat(String str)
拼接字符串,不该面原字符串 boolean contains(String str)
是否包含该子串 boolean equals(Object o)
是否相等 byte[] getBytes()
将字符串转化为字节数组 通过 String
的构造方法将字节数组转化为字符串int indexOf(int ch, int index)
指定下标开始寻找指定字符第一次出现的位置 static String valueOf()
将传入值转换为字符串 传入对象则会调用对象的 toString()
;
传入字符数组对象,则打印其内容String replaceAll(String reg, String str)
替换指定内容 boolean matches(String reg)
是否匹配指定规则 String[] split(String reg)
按指定规则切割字符串 作为切割的符号会被消除;
若两个切割符号相连,则会被分出一个空字符串""
特别地
拼接字符串可以使用运算符"
+
",本质上 Java 编译器会调用StringBuffer
(或类似技术)来实现这个拼接操作。拼接多个字符串建议使用
StringBuilder
类,少量字符串使用+
运算符StringBuilder
和StringBuffer
使用方法完全一致StringBuilder
线程不安全StringBuffer
线程安全
故代码:
InputString s = "a"; s += "b";
1
2实际上的执行效果是:
String s = "a"; s = new StringBuilder("a").append("b").toString();
1
2在最后的
toString()
中生成了新的字符串对象,类似于(真实过程更加复杂):s = new String ("ab");
1
分析代码
Input
String s1 = "ab";
String s2 = new String("ab");
String s4 = "a";
s4 += "b";
2
3
4
第一句
String s1 = "ab";
1内存图:
第二句
String s2 = new String("ab");
1内存图:
第三句
String s4 = "a";
1内存图:
第四句
s4 += "b";
1由
StringBuilder
实现+=
操作,具体步骤为:生成
StringBuilder
对象new StringBuilder("a")
1内存图:
StringBuilder
对象取append()
方法拼接字符串new StringBuilder("a").append("b")
1内存图:
堆内存0x3f4c
断开与常量"a"(0x45fa
)的链接,转而链接常量"ab"(0x003d
)。调用
toString()
生成新的String
对象new StringBuilder("a").append("b").toString()
1内存图:
将新生成的
String
对象的管理权交给s4
(赋值)s4 = new StringBuilder("a").append("b").toString();
1内存图:
栈内存内s4
断开与常量"a"(0x45fa
)的链接,转而链接堆内存0x7bce
。结束操作,最终结果
内存图:
关于编码
按照某些规律将字符映射成字节。这个记录规则就是编码表
名称 | 内容 | 特点 |
---|---|---|
ASCII | 0 至 127 | 不完全 |
西欧码表 ISO-8859-1 | 西欧字符 | 一个字母占 1 字节 |
GB2312 | 常见基本简体汉字和部分常用繁体汉字 | 一个字符占 2 字节 |
UTF-8 | 常见语言的常见字符 | 一个字符占 3 字节 |
# 4.5.3 正则表达式
正则表达式本质上是指定匹配或筛选规则的一系列表达式。
规则
元字符与限定符:正则表达式中含有表达特殊意义的字符,这些字符成为元字符;在正则表达式中,需要表示元字符出现次数等逻辑规则时,使用限定符来表示。
在 Java 中,由于使用
\
转义且某些元字符中本身包含\
,故在使用时需要写作\\
。如:表示任意一个数字的正则表达式在 Java 中写作\\d
。
元字符/限定符 | 描述 |
---|---|
. | 任意字符 |
\d | 0至9任意一个数字 |
\D | 任意一个非数字 |
\s | 空格类字符,如\t , \n , \x0B , \f , \r |
\S | 任意一个非空格类字符 |
\w | 除$ 外的可用于标识符的字符(字母(a-zA-Z)、数字(0-9)、下划线(_)) |
\W | 任意一个不能用于标识符的字符 |
^ | 串开头 |
$ | 串结尾 |
| | 或 |
+ | 出现1次或多次 |
? | 出现0次或1次 |
* | 出现0次或多次 |
{n} | 出现n次 |
{n,} | 出现至少n次 |
{n,m} | 出现n至m次 |
() | 捕获组 |
[] | 单个字符 |
\n | 编号为n的捕获组 |
这里:{n,m|n,m∈N+}
捕获组
起编号作用
从左括号出现的位置开始计算
例如:(A((BC(D))E))F)
捕获组 | 内容 |
---|---|
\\1 | A((BC(D))E) |
\\2 | (BC(D))E |
\\3 | BC(D) |
\\4 | D |
\\5 | F |
String
类中的使用
使用
boolean matches(String regex)
来使用正则表达式验证字符串是否符合规则。String
类还提供了其他的验证规则函数,如:boolean startsWith(String prefix)
用来验证是否由某字符串打头。
# 4.6 包装类
# 4.6.1 基本信息
对于每种基本数据类型, Java 都提供了与其对应的类。这些类称为包装类。
基本数据类型 | byte | short | int | long | float | double | char | boolean |
---|---|---|---|---|---|---|---|---|
包装类 | Byte | Short | Integer | Long | Float | Double | Character | Boolean |
int
和char
所对应的包装类为单词的全拼。
# 4.6.2 装箱
将基本数据类型转换为对应的引用数据类型对象的操作。
# 4.6.3 自动装箱 Java SE 5.0+
将一个基本数据类型变量直接赋值给对应的引用数据类型对象。本质上调用了对应的valueOf()
。
例如:
Integer integer = 3;
相当于:
Integer integer = Integer.valueOf(3);
注意
所有相同类型地包装类对象之间值的比较,应当全部使用equals()。
在值范围在 -128 到 127内的赋值,Integer对象会在IntegerCache.cache中产生,会服用已有对象。此时使用==比较是安全的。
但在范围之外的所有数据会在堆中产生,不会复用已有对象。
故推荐全部使用equals()来规避风险。
# 4.6.4 自动拆箱 Java SE 5.0+
将一个引用数据类型对象直接赋值给对应基本数据类型变量。本质上调用了对象的xxxValue()
。
例如:
int i = integer;
相当于:
int i = integer.intValue();
当发生基本数据类型和包装类运算时,会发生自动拆箱。
关于哈希码
整数的哈希码是其本身,但小数的哈希码需要经过计算才能得到。
字符的哈希码是其对应的编码。
布尔类型的哈希码为特殊值,如
true
的哈希码为1231
;false
为1237
。八种基本数据类型的哈希码都为固定值。
# 4.7 Math
类
# 4.7.1 基本信息
Package java.lang
public final class Math
Math
类是一个最终类,其构造函数是私有的。
该类提供了一系列静态方法,这些方法实现了基本的数学运算,如三角函数、绝对值、平方根等。
# 4.7.2 重要方法
static double ceil(double a)
向上取整static double floor(double a)
向下取整static long round(double a)
/static int round(float a)
四舍五入static double sqrt(double a)
求平方根static double pow(double a, double b)
求幂 (ab)static double random()
返回一个随机数 (0.0≤x<1.0)
# 4.7.3 strictfp
关键字
精确浮点(strict float point),用于修饰类、接口和方法。
被修饰的代码在执行中以80位二进制数来运算小数,结果会保留为64位。
特别的
当适用精确运算时,Java 提供了BigDecimal
类。
这个类中对基础运算(如加、减、乘、除)提供了方法支持,故,不能使用运算符(如+
、-
、*
、/
)来进行运算。
# 4.8 反射
# 4.8.1 基本信息
Package java.lang
public final class Class<T>
Package java.lang.reflect
Java 提供了反射机制,使用该机制可以动态操作 Java 代码(例如程序经过编译后的变动),也可以利用其来分析类的具体能力。它也体现了高内聚低耦合的设计思想。
# 4.8.2 Class
类
Class
类的实例代表运行中的 Java 应用程序中的类和接口。枚举是类的一种,注解是接口的一种。
每个数组也都属于一个类,该类反映为一个 Class
对象,该对象被所有具有相同元素类型和维数的数组共享。
Java 的原始类型(布尔、字节、char
、short
、int
、long
、float
和 double
)以及关键字 void
也被表示为 Class
对象。(即存在 int.class
, void.class
等 Class
对象)。
Class
没有公共构造函数。相反,Class
对象是由 Java 虚拟机在加载类时自动构建的,并通过调用类加载器中的 defineClass()
方法来构建。
获取 Class 对象
通过获取具体类的 Class 对象(某些地方也称为字节码对象),我们可以利用它们获取该类的类信息。获取方法:
对象.getClass()
通过某类的具体实例来获取该类的Class
对象。调用了 Object 类中的方法来实现。类名.class
每个类都有一个隐含的静态属性class
, 通过类名直接获取该属性来获取到Class
对象。Class.forName("类全路径")
Class
类的静态方法,获取Class
对象。
它是一种动态加载类的方法,这样的加载方式不在程序编译期完成,而是在运行时再动态加载。
例如:class Main { public static void main(String[] args) { Admin admin = new Admin(); admin.login(); User user = new User(); user.login(); } }
1
2
3
4
5
6
7
8
9这样的主函数经过编译后,编译器无法找到类
Admin
和User
以及它们所对应的login()
而报错。这样的类加载形式是静态加载。进行改造:
// 统一的人员接口 interface Person { public void login(); } // 具体实现 class Admin implements Person { @Override public void login() { System.out.println("Admin login."); } } class User implements Person { @Override public void login() { System.out.println("User login."); } } // 主函数 class Main { public static void main(String[] args) { // 通过传入参数动态加载类 Class personClass = Class.forName(args[0]); // 创建实例 Person person = (Person) personClass.newInstance(); person.login(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31通过这样的改造,主函数不必在编译时期就指定具体的
Admin
或者User
类,即使它们暂时不存在也不影响主函数编译失败。在程序运行时,给程序传入具体要加载的类动态加载并调用其login()
来完成整个功能。
获取构造函数
class对象.getConstructor(构造函数参数类型class对象)
返回指定参数类型的公共构造函数。
例如:public class Person { // 属性 // 有参构造方法 public Person(String name, int age) { this.age = age; this.name = name; } } // main 函数中,获取到 class 对象 cl 后 // 获取有参构造函数(传入构造方法需要的 String 和 int 类型的 class 对象) Constructor con = cl.getConstructor(String.class, int.class);
1
2
3
4
5
6
7
8
9
10
11
12
13class对象.getConstructors()
获取所有公共构造函数。class对象.getDeclaredConstractors(构造函数参数类型字class对象)
返回指定参数类型的全部构造函数(包括public
private
等)。
获取实例对象
class对象.newInstance()
要求存在无参数构造函数
获取类属性
class对象.getFields("属性名")
获取所有公有属性class对象.getDeclaredFields("属性名")
获取所有属性
获取方法对象
class对象.getMethod("方法名", 方法对应参数的class对象)
获取公有方法class对象.getDeclaredMethod("方法名", 方法对应参数的class对象)
获取所实现的接口
class对象.getInterfaces()
其他常用方法
名称 | 作用 |
---|---|
class对象.getName() | 获取类全路径名 |
class对象.getPackage() | 获取类所在包 |
class对象.getSimpleName() | 获取当前类名 |
class对象.getSuperclass() | 获取父类名 |
class对象.isAnonymousClass() | 是否是匿名内部类 |
class对象.isLocalClass() | 是否是方法内部类 |
class对象.isPrimitive() | 是否是基本类型 |
class对象.isArray() | 是否是数组 |
class对象.isEnum() | 是否是枚举 |
class对象.isInstance(指定对象) | 判断指定对象是否是该类的实现 |
class对象.isInterface() | 是否是接口 |
class对象.isAssignableFrom(目标类型) | 判断目标类型是否是当前类的本身或子类 |
Object
与 Class
Object
是顶级父类,Class
也继承自Object
.Class
类用于反射,它表示了 Class 这样的一种类,可以利用它来进一步获取关于类的各种信息。Class
类的实例表示了当前运行着的 Java 程序的类,每一个类都会在运行时自动创建出它对应的Class
类实例。Class
类的构造函数私有,只能通过 JVM 来访问。所以无法手动创建Class
类的实例。
# 4.8.3 Constructor
类
描述构造方法的类。
获取实例对象
constructor对象.newInstance()
获取构造方法返回值类型
constructor对象.getType()
返回值是 Class
类型变量
获取构造方法参数列表
constructor对象.getParameterTypes()
# 4.8.4 Field
类
描述属性的类。
获取指定对象的属性值
field对象.get(指定对象)
可能需要使用 .setAccessible(true)
来暴力破解访问权限限制。
设置指定对象的属性值
field对象.set(指定对象)
获取属性声明类型
field对象.getType()
返回值是 Class
类型变量
获取属性名称
field对象.getName()
# 4.8.5 Method
类
描述方法的类。
执行方法
method对象.invoke(作用对象, 参数)
如果方法有返回值类型则返回该类型变量,若方法无返回则返回 null
破解权限
method对象.setAccessible(true)
允许在类外执行,一般配合执行方法一起使用。
获取方法返回值类型
method对象.getReturnType()
获取方法参数列表
method对象.getParameterTypes()
获取抛出异常
method对象.getExceptionTypes()
判断是否含有可变参数
method对象.inVarArgs()