Java面向对象(下)-1
对应《疯狂Java讲义(第5版)》6.1-6.4 章节
包装类
即8个基本类型包装为对象。
基本类型在栈中直接存储的具体数值,而包装类型则存储的是堆中的引用。
相比较于基本类型而言,包装类型需要占用更多的内存空间,但基本类型不具备“对象”的特性。
基本数据类型(默认值) | 包装类(默认值) | 取值范围 |
---|---|---|
byte (0) | Byte (null) | -128~127 |
short (0) | Short (null) | -32768~32767 |
int (0) | Integer (null) | -231 ~ 2(31-1) |
long (0) | Long (null) | -263 ~ 2(63-1) |
float (0.0) | Float (null) | 1.4E-45~3.4028235E38 |
double (0.0) | Double (null) | 4.9E-324~1.7976931348623157E308 |
boolean (false) | Boolean (null) | true或false |
char (为空) | Character (null) | 0~65535 |
自动装箱,自动拆箱(JDK 1.5)
定义:基本数据类型和包装类之间可以自动地相互转换
理解:装箱就是自动将基本数据类型转换为封装类型,拆箱就是自动将封装类型转换为基本数据类型
1 |
|
字符串和基本类型转换
类型 | 方法 |
---|---|
字符串转基本型 | 使用包装类的 parseXXX 或 valueof 静态方法 |
基本型转字符串 | 使用包装类的 toString 或 String类的valueof 静态方法 |
1 |
|
包装类和基本类型之间的比较
1 |
|
第一段代码,基本类型和包装类型进行 == 比较,这时候 b 会自动拆箱,直接和 a 比较值,所以结果为 true;
第二段代码,两个包装类型都被赋值为了100,这时候会自动装箱。-128 到 127 之间的整型对象是从
IntegerCache
中获取然后比较,所以结果为 true;TIPS:当需要进行自动装箱时,如果数字在 -128 至 127 之间时,会直接使用缓存中的对象,而不用重新创建一个对象。
第三段代码,两个包装类型重新被赋值为了200,这时候仍然会进行自动装箱,结果是 true,但两个包装类的对象不一致,结果为false。
此时 == 操作符应用于两个引用类型的比较,比较的是两个引用类型的引用地址是否相同,即是否为同一个对象。
Java7为所有包装类提供compare
静态方法
java.lang包的Integer类的compare()方法比较作为参数给出的两个整数值(x,y),如果(x == y)则返回零,如果(x < y)则返回小于零的值,如果(x > y),则返回大于零的值。
整形包装类无符号数运算
参考《 疯狂java讲义第五版》P171
打印对象 和 toString方法
toString()是一个“自我描述”方法,通常继承于Object类,其返回值类型为String类型,返回类名和它的引用地址,如Person@15db9742
对象打印自动调用toString方法
1 |
|
在进行String类与其他类型的连接操作时,自动调用toString()方法,demo如下:
1 |
|
重写
1 |
|
== 和 equals方法
“==”比较基本数据类型时比较数值是否相等(不要求数据类型严格相同),而比较两个对象时比较的是两个对象的内存地址值,即是否指向同一对象(对象必须同类型或有父子关系)
对于equals()方法(默认从Object继承),注意:equals方法不能作用于基本数据类型的变量
如果没有对equals()方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容
如何正确重写equals方法?
- 对称性:如果
x.equals(y)
返回true
,那么y.equals(x)
也应该返回true
。 - 传递性:如果
x.equals(y)
和y.equals(z)
都返回true
,那么x.equals(z)
也应该返回true
。 - 一致性:如果对象没有被修改,那么多次调用
x.equals(y)
应该始终返回true
或false
。 - 非空性:
x.equals(null)
应该返回false
。 - 自反性:
x.equals(x)
应该返回true
。
在重写equals
方法时,我们应该考虑上述五个原则。此外,通常我们还需要重写hashCode
方法,以确保满足散列合同的约定。
下面是一个Person
类重写equals
方法的示例:
obj.getClass() != Person.class 比 obj instanceof Person 好
1 |
|
类成员 static
static不能修饰构造器,
类成员属于整个类,不属于单个对象,但可通过对象(即使为null)访问类成员,实际仍通过类访问
类成员(static修饰)无法访问实例成员,因为类成员初始化完成时,实例成员不一定初始化完成
单例(Singleton)类
类构造器由private修饰,隐藏起来,提供一个Public方法(必须为static),用于创建和访问该类对象
1 |
|
final修饰符
表示修饰的类、方法和变量不可改变
修饰变量时,表示获得初始值后不可被重新赋值
final成员变量
必须显示指定初始值
必须在初始化块、声明变量时或构造器(非静态变量)中指定初始值
final修饰引用变量时,只保证引用地址不发生改变,但引用的对象可能发生改变
final 宏变量
宏变量相当于一个直接量,程序会直接把宏变量替换成直接量,成为宏变量的条件如下:
- final修饰
- 定义变量时指定了初始值
- 该初始值在编译时就可以确定下来
其2中包括赋直接量,或者基本算数表达式或字符串连接运算,没有访问普通变量或调用方法即可
final方法和final类
final修饰public方法时,表示其不可被重写
final修饰private方法用处不大,因为private方法无法继承,更无法重写,如果*子类出现完全相同的方法,*也只是重新定义了一个新方法
final修饰的方法仍可重载
final修饰类,表示该类不可被继承
不可变(Immutable)类
不可变类(Immutable class)是指当一个对象被创建出来以后,它的值就不能被修改了,也就是说,一个对象一旦被创建出来,在其整个生命周期中,它的成员变量就不能被修改了。它有点类似于常量(const),只允许别的程序读,而不允许别的程序进行修改。如8个包装类以及java.lang.String类
在Java类库中,所有基本类型的包装类都是不可变类,例如Integer、Float等。此外,String也是不可变类。
原则
- 类中所有的成员变量被private和final所修饰
- 提供带参数的构造器或实例方法,根据参数初始化成员变量
- 仅提供成员变量的getter方法
- 如果某成员变量为引用变量,需通过new新建临时对象并克隆该成员变量值后返回
- 如果有必要,可以通过覆盖 Object 类的 equals()方法和hashCode()方法。在 equals()方法中,根据对象的属性值来比较两个对象是否相等,并且保证用 equals()方法判断为相等的两个对象的hashCode()方法的返回值也相等,这可以保证这些对象能正确地放到HashMap或HashSet集合中
缓存实例的不可变类
不可变类的实例状态不可变,可以方便的被多个对象共享。若程序经常使用相同的不可变类实例,则应考虑缓存改实例,从而避免反复创建该对象,降低系统开销。但是也不能盲目使用缓存,因为缓存对象会占用系统内存。
可借助数组实现缓存,例如Integer类