Java基础知识:
覆写Object方法
因为所有的class
最终都继承自Object
,而Object
定义了几个重要的方法:
toString()
:把instance输出为String
;equals()
:判断两个instance是否逻辑相等;hashCode()
:计算一个instance的哈希值。
在必要的情况下,我们可以覆写Object
的这几个方法。例如:
class Person {
...
// 显示更有意义的字符串:
@Override
public String toString() {
return "Person:name=" + name;
}
// 比较是否相等:
@Override
public boolean equals(Object o) {
// 当且仅当o为Person类型:
if (o instanceof Person) {
Person p = (Person) o;
// 并且name字段相同时,返回true:
return this.name.equals(p.name);
}
return false;
}
// 计算hash:
@Override
public int hashCode() {
return this.name.hashCode();
}
}
调用super
在子类的覆写方法中,如果要调用父类的被覆写的方法,可以通过super
来调用。例如:
class Person {
protected String name;
public String hello() {
return "Hello, " + name;
}
}
Student extends Person {
@Override
public String hello() {
// 调用父类的hello()方法:
return super.hello() + "!";
}
}
final
继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final
。用final
修饰的方法不能被Override
:
class Person {
protected String name;
public final String hello() {
return "Hello, " + name;
}
}
Student extends Person {
// compile error: 不允许覆写
@Override
public String hello() {
}
}
如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记为final
。用final
修饰的类不能被继承:
final class Person {
protected String name;
}
// compile error: 不允许继承自Person
Student extends Person {
}
对于一个类的实例字段,同样可以用final
修饰。用final
修饰的字段在初始化后不能被修改。例如:
class Person {
public final String name = "Unamed";
}
对final
字段重新赋值会报错:
Person p = new Person();
p.name = "New Name"; // compile error!
可以在构造方法中初始化final字段:
class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}
这种方法更为常用,因为可以保证实例一旦创建,其final
字段就不可修改。
相等关系
相等关系是一种等价关系,即满足自反、对称、传递
可以用"是否为等价关系"来检验equals()是否正确
Immutable类型的相等
1.判相等要从A空间来看(用户角度) AF映射到相同结果,则等价
2.站在外部观察者角度:对两个对象调用任何相同的操作,都会得到相同的结果,则认为这两个对象是等价的。
== vs. equals()
1.== 表示的是引用等价性(一般用于基本数据类型的相等判定)
==操作符会比较引用。它测试参考等式。如果两个引用指向内存中的相同存储器,则它们是==。在快照图中,如果两个引用的箭头指向同一个对象气泡,则这两个引用为==(如果用==,是在判断两个对象身份标识 ID是否相等(指向内存里的同一段空间) )
2.equals()表示的是对象等价性 (用于对象类型相等判定)
在自定义ADT时,需要重写Object 的 equals() 方法
equals()方法的实现(Equality of Immutable Types)
在Objects中实现的缺省equals()是在判断引用相等性(相当于==);
在java中编写equal方法时需要注明@override,帮助检测标签是否正确;
用instanceof操作可以判断对象是否是一种特殊的类型(用instanceof是一种动态类型检查,而不是静态类型检查);
注意:不能在父类中用instanceof判断子类类型
等价的对象必须拥有相同的hashCode;不相等的对象也可以映射为同样的hashCode,但是性能会变差
重写equals方法必须要重写hashCode方法(除非能保证你的ADT不会被放入到Hash类型的集合中)
在这个例子中,d1和d2是相等的,但它们有不同的哈希码。确保满足契约的一个简单而激烈的方法是,hashCode总是返回一些常量值,因此每个对象的哈希代码都是相同的。
改进方法如下:
mutable类型的相等
观察等价性:在不改变状态的情况下,两个mutable对象是否看起来一致
行为等价性:调用对象的任何方法都展示出一致的结果
对于mutable类型来说,往往倾向于实现严格的观察等价性(但是在有些时候,观察等价性可能导致bug,甚至破坏RI)
注意:如果某个mutable的对象包含在Set集合类中,当其发生改变后,集合类的行为不确定!
Collections 使用的是观察等价性,但是其他的mutable类(如StringBuilder)使用的是行为等价性
对mutable类型,实现行为等价性即可。也就是说只有指向同样内存空间的objects,才是相等的,所以对mutable类型来说,无需重写这两个函数,直接调用Object的两个方法即可。(如果一定要判断两个对象"看起来"是否一致,最好定义一个新方法,e.g. similar() )
immutable类型必须重写equals() 和 hashCode()
mutable类型可以不重写,直接继承自Object
clone()
clone()创建并返回对象的一个copy
Autoboxing
Integer 和 int 注意区别
flase
(Numbers between -128 and 127 are true.)