目录
常用类的概述和使用
Object类的概述
基本概念
java.lang.Object
类是Java语言中类层次结构的根类,也就是说任何一个类都是该类的直接或者间接子类。- 如果定义一个Java类时没有使用extends关键字声明其父类,则其父类为
java.lang.Object
类。Object类定义了“对象”的基本行为,被子类默认继承。
常用方法
方法声明 | 功能介绍 |
---|---|
Object() | 使用无参方式构造对象 |
boolean equals(Object obj) | 用于判断调用对象是否与参数对象相等。 该方法默认比较两个对象的地址是否相等,与==运算符的结果一致。若希望比较两个对象的内容,则需要重写该方法。 若该方法被重写后,则应该重写hashCode方法来保证结果的一致性。 |
int hashCode() | 用于获取调用对象的哈希码值(内存地址的编号)。 若两个对象调用equals方法相等,则各自调用该方法的结果必须相同 若两个调用对象equals方法不相等,则各自调用该方法的结果应该不相同。 为了使得该方法与equals方法保持一致,需要重写该方法。 |
String toString() | 用于获取调用对象的字符串形式 该方法默认返回的字符串为:包名.类名@哈希码值的十六进制 为了返回更有意义的数据,需要重写该方法 使用print或println打印引用或字符串拼接引用都会自动调用该方法 |
Class<?> getClass() | 用于返回调用对象执行时的Class实例,反射机制使用 |
equals() 与 ==
-
对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。
-
对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。
Integer x = 1; Integer y = 1; System.out.println(x.equals(y)); // true System.out.println(x == y); // false
equals方法的实现
- 检查是否为同一个对象的引用,如果是直接返回true
- 检查是否为同一个类型,如果不是,直接返回false
- 将Object对象进行转换
- 判断每个关键域是否相等
public class EqualExample {
private int x;
private int y;
private int z;
public EqualExample(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
EqualExample that = (EqualExample) obj;
return x == that.x && y == that.y && z == that.z;
}
}
hashCode()
-
hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。
-
在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。
-
下面的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。我们希望将这两个对象当成一样的,只在集合中添加一个对象,但是因为 EqualExample 没有实现 hasCode() 方法,因此这两个对象的散列值是不同的,最终导致集合添加了两个等价的对象。
EqualExample e1 = new EqualExample(1, 1, 1); EqualExample e2 = new EqualExample(1, 1, 1); System.out.println(e1.equals(e2)); // true HashSet<EqualExample> set = new HashSet<>(); set.add(e1); set.add(e2); System.out.println(set.size()); // 2
-
理想的散列函数应当具有均匀性,即不相等的对象应当均匀分布到所有可能的散列值上。这就要求了散列函数要把所有域的值都考虑进来,可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位。
一个数与 31 相乘可以转换成移位和减法:
31*x == (x<<5)-x
,编译器会自动进行这个优化。@Override public int hashCode() { int result = 17; result = 31 * result + x; result = 31 * result + y; result = 31 * result + z; return result; }
包装类
包装类的概念
通常情况下基本数据类型的变量不是对象,为了满足万物皆对象的理念就需要对基本数据类型的变量进行打包封装处理变成对象,而负责将这些变量声明为成员变量进行对象化处理的相关类,叫做包装类。
包装类的分类
包装类 | 对应的基本数据类型 |
---|---|
java.lang.Byte | byte |
java.lang.Short | short |
java.lang.Integer | int |
java.lang.Long | long |
java.lang.Float | float |
java.lang.Double | double |
java.lang.Boolean | boolean |
java.lang.Character | char |
Integer类的概述
ava.lang.Integer
类内部包装了一个int类型的变量作为成员变量,主要用于实现对int类型的包装并提供int类型到String类之间的转换等方法。
常用的常量
常量类型和名称 | 功能介绍 |
---|---|
public static final int MAX_VALUE | 表示int类型可以描述的最大值,即2^31-1 |
public static final int MIN_VALUE | 表示int类型可以描述的最小值,即-2^31 |
public static final int SIZE | 表示int类型采用二进制补码形式的位数 |
public static final int BYTES | 表示int类型所占的字节个数 |
public static final ClassTYPE | 表示int类型的Class实例 |
常用的方法
方法声明 | 功能介绍 |
---|---|
Integer(int value) | 根据参数指定的整数来构造对象(已过时) |
Integer(String s) | 根据参数指定的字符串来构造对象(已过时) |
int intValue() | 获取调用对象中的整数值并返回 |
static Integer valueOf(int i) | 根据参数指定整数值得到Integer类型对象 |
boolean equals(Object obj) | 比较调用对象与参数指定的对象是否相等 |
String toString() | 返回描述调用对象数值的字符串形式 |
static int parseInt(String s) | 将字符串类型转换为int类型并返回 |
static String toString(int i) | 获取参数指定整数的十进制字符串形式 |
static String toBinaryString(int i) | 获取参数指定整数的二进制字符串形式 |
static String toHexString(int i) | 获取参数指定整数的十六进制字符串形式 |
static String toOctalString(int i) | 获取参数指定整数的八进制字符串形式 |
装箱和拆箱的概念
- 在Java5发布之前使用包装类对象进行运算时,需要较为繁琐的“拆箱”和“装箱”操作;即运算前先将包装类对象拆分为基本类型数据,运算后再将结果封装成包装类对象。
- 从Java5开始增加了自动拆箱和自动装箱的功能。
自动装箱池
在Integer类的内部提供了自动装箱池技术,将-128到127之间的整数已经装箱完毕,当程序中使用该范围之间的整数时,无需装箱直接取用自动装箱池中的对象即可,从而提高效率。
BigDecimal类的概述
基本概念
由于float类型和double类型在运算时可能会有误差,若希望实现精确运算则借助java.math.BigDecimal
类型加以描述。
常用的方法
方法声明 | 功能介绍 |
---|---|
BigDecimal(String val) | 根据参数指定的字符串来构造对象 |
BigDecimal add(BigDecimal augend) | 用于实现加法运算 |
BigDecimal subtract(BigDecimal subtrahend) | 用于实现减法运算 |
BigDecimal multiply(BigDecimal multiplicand) | 用于实现乘法运算 |
BigDecimal divide(BigDecimal divisor) | 用于实现除法运算 |
BigInteger类的概念
基本概念
若希望表示比long类型范围还大的整数数据,则需要借助java.math.BigInteger
类型描述。
常用的方法
方法声明 | 功能介绍 |
---|---|
BigInteger(String val) | 根据参数指定的字符串来构造对象 |
BigInteger add(BigInteger val) | 用于实现加法运算 |
BigInteger subtract(BigIntegerval) | 用于实现减法运算 |
BigInteger multiply(BigInteger val) | 用于实现乘法运算 |
BigInteger divide(BigInteger val) | 用于实现除法运算 |
BigInteger remainder(BigInteger val) | 用于实现取余运算 |
BigInteger[] divideAndRemainder(BigInteger val) | 用于实现取商和余数的运算 |
关于包装类的常见问题
支持缓存操作的包装类有哪几种
- Java在几种包装类中提供了缓存设计,会对一定范围内的数据作缓存,如果数据在范围内,会优先从缓存中取数,超出范围才会创建新对象。
- Byte、Short、Integer、Long:缓存[-128, 127]区间的数据
- Character:缓存[0, 127]区间的数据
- Boolean:缓存true、false
- Double、Float并不支持缓存技术
方法重载时,如重载方法的参数分别为基本数据类型与包装类,会如何执行调用?
当方法以基本数据类型和其对应包装类作为方法重载的参数条件时,调用原则时:各回各家、各找各妈
。
public class Test {
public static void main(String[] args) {
testAge(1); // 我是基本数据类型做参数的方法
testAge(Integer.valueOf(1)); // 我是包装类做参数的方法
}
public static void testAge(Integer i) {
System.out.println("我是包装类做参数的方法");
}
public static void testAge(int i) {
System.out.println("我是基本数据类型做参数的方法");
}
}