|Practical Java| Chapter 2 Objects and Equality (对象和相等性)
Java提供的 Object / primitive Types /equality 三个概念是进行classes 设计的
重要基础.思考: 对象和基本类型的使用方式.
08> Java中的两种截然不同的两种类型: reference 和 primitive Types,
后者称为built-in (内置类型), 其拥有对应的Wrapper classes (包装类)
references 和 primitives 的行为方式及语义全然不同.
Ex: int i =5; //primitive type
Integer j = new Integer(10); //object reference
这两个变量 i, j 都存储在局部变量表, 他们的操作都在Java操作数堆栈(operand Stack)
中进行,都二者所表述的意义安全不同. 不论是 int 或者 Object reference, 她们都在
stack中占据32bits空间,(JVM表述一个int或一个o-r 最少要32bits存储空间)但Integer
对象在stack 中记录的并不是对象本身,而是对象的reference.!!
所有Java 对象都是通过 Object references 来访问的, 那是某种形式的指针,该指针指
向Heap 中的某块内存区域, Heap 则为对象的生存提供了真实存储场所.
作为基本类型 --primitive Types 在其声明时即分配了一分存储空间.
reference 和 primitive 类型具有不同的特性和用法.前者缺省值为null, 而
后者的缺省值取决于具体的types. 应该尽量避免两者的混和使用!!
Ex: Point a = new Point(0, 0); Point b = new Point(1, 1);
a = b; //a 指向 (1, 1);
a.setLocation(5, 5); //a, b 都指向 (5, 5);
PS: 应该记住对于a ,b 两者都是对象的引用, 当执行 a = b 后, a ,b此时指向
同一个对象! 对于a, b的操作实则是对同一对象的操作.
(a 一开始所指向的对象 (0, 0) 则成为 Java gc的目标.)
09> 区分 == 和 equals();
掌握好了primitive Types 和 Object references 的特性, 对于 " == " 和 equals() 区别
应该是小case了^_^:
(这里不得不再提醒自己一次对于 Integer a = new Integer(10); 认识到a 作为对象
引用的伟大! --- 从而进一步理解参数传递的by value .)
对于 " ==" , 她只是进行浅层的测试相等性, 即变量的值. 显然作为引用, 指向对象
同则值肯定不等. 故对于对象, 应该用 equals() 方法检测相等性.
Ex: 另外一个问题:
Integer ia = new Integer(10);
Float fa = new Float(10.0f);
System.out.println(ia.equals(fa) ); //false
---> 不同基本类型的数值彼此可能相等, 因为可以自动类型转换;
---> 对于两个律属不同classes的对象决不会被认为彼此相等.
10> 不要依赖 equals() 方法的缺省实现
Mission: 计算库存中Golfball的数量. 此时你会有个 class Golfball{}
Golfball gb1 = new Golfball("Brandx", "Pro", 100);
Golfball gb2 = new Golfball("Brandx", "Pro", 100);
当执行 gb1.equals(gb2) 时得到的是 false!!
==>> 考虑 paraxi09> 为Integer, 她有自己的equals()方法,
而Golfball 没有, 故调用的是 java.lang.object的equals() {浅比较 }
所以在这个Mission中必须实现Golfball 自己的equals()方法.
PS: 对于隶属 primitive Types 的变量用" == " 操作符,
对于隶属classes 的 Object reference 用的是" equals()";
一个小插曲: 当上例中的Brand 变量由 String 变为 BufferString类型时结果又成
False了,这是因为BufferString类没有实现equals()方法.
总结: A> 若要比较对象是否相等, 其class有责任提供一个正确的equals();
B> 在[ 想当然的调用equals() 之前,请检查所用的class的确实现了equals();
C> 当java.lang.object的缺省函数不能胜任要求时,就应该在所用类中覆盖equals();
11> 实现equals() 时必须深思熟虑
当 [class objects 相等与否] 的检验工作超过了 [Object reference之间的单纯比较]
时, 该class 就应当提供一个equals(). 即如果占用不同内存空间的两个对象有可
能被视为逻辑上相同, 那个这个class 就应当提供equals();
12> 实现equals() 时优先考虑使用 getClass() 方法
对于强类型参数(Strong argument)
如果两个对象隶属不同的class 或 Types, 则她们必不相等.
对于equals()而言, 惟有相同的class 所产生的对象才能被视为相等. --->getClass();
Ex: class Base{
public boolean equals(Object obj){
if (getClass() != obj.getClass() )
return false;
// ..........
}
}
==>> getClass() 会返回某个对象的运行时类(runntime class), 故如果上述两个对象
并非都隶属于Base, 则equals()返回 false.
getClass() 在比较Base 和 Derived 对象时总是返回 false;
对于同一个class的对象, getClass()测试的是对象的 attributes, 即被用来比较
的值域(fields).