目录
Object 类
以后定义的所有类都是 Object 类的子类,也都具备 Object 类的所有特性。
Object 类基本特性
Object 类是所有 Java 类的根基类,也就意味着所有的 Java 对象都拥有 Object 类的属性和方法。如果在类的声明中未使用 extends 关键字指明其父类,则默认继承 Object 类。
public class Person {
...
}
//等价于:
public class Person extends Object {
...
}
toString 方法
Object 类中定义有 public String toString()方法,其返回值是 String 类型。Object 类中 toString 方法的源码为:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
根据如上源码得知,默认会返回“类名+@+16 进制的 hashcode”。在打印输出或者用字符 串连接对象时,会自动调用该对象的 toString()方法。
重写 toString()方法
public class Test01 {
public static void main(String[] args) {
Person1 p=new Person1();
p.age=20;
p.name="李斯";
System.out.println("info:"+p);
Test t = new Test();
System.out.println(t);
}
}
class Person1 {
String name;
int age;
@Override
public String toString() {
return name+",年龄:"+age;
}
}
==和 equals 方法
“==”代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地 址相等即是同一个对象。
Object 类中定义有:public boolean equals(Object obj)方法,提供定义“对象内容相等”的 逻辑。比如,我们在公安系统中认为 id 相同的人就是同一个人、学籍系统中认为学号相同 的人就是同一个人。
Object 的 equals 方法默认就是比较两个对象的 hashcode,是同一个对象的引用时返回 true 否则返回 false。但是,我们可以根据我们自己的要求重写 equals 方法。
自定义类重写 equals()方法
public class TestEquals {
public static void main(String[] args) {
Person2 p1 = new Person2(123,"张三");
Person2 p2 = new Person2(123,"李斯");
System.out.println(p1==p2); //false,不是同一个对象
System.out.println(p1.equals(p2)); //true,id相同则认为两个对象内容相同
String s1 = new String("北京大学");
String s2 = new String("北京大学");
System.out.println(s1==s2); //false, 两个字符串不是同一个对象
System.out.println(s1.equals(s2)); //true, 两个字符串内容相同
}
}
class Person2 {
int id;
String name;
public Person2(int id,String name) {
this.id=id;
this.name=name;
}
public boolean equals(Object obj) {
if(obj == null){
return false;
}else {
if(obj instanceof Person2) {
Person2 c = (Person2)obj;
if(c.id==this.id) {
return true;
}
}
}
return false;
}
}
JDK 提供的一些类,如 String、Date、包装类等,重写了 Object 的 equals 方法,调用这 些类的 equals 方法, x.equals (y) ,当 x 和 y 所引用的对象是同一类对象且属性内容相等时 (并不一定是相同对象),返回 true 否则返回 false。
super 关键字
super 是直接父类对象的引用。可以通过 super 来访问父类中被子类覆盖的方法或属性。
使用 super 调用普通方法,语句没有位置限制,可以在子类中随便调用。
若是构造方法的第一行代码没有显式的调用 super(...)或者 this(...);那么 Java 默认都会调 用 super(),含义是调用父类的无参数构造方法。这里的 super()可以省略。
public class TestSuper01 {
public static void main(String[ ] args) {
new ChildClass().f();
}
}
class FatherClass {
public int value;
public void f(){
value = 100;
System.out.println ("FatherClass.value="+value);
}
}
class ChildClass extends FatherClass {
public int value;
public void f() {
super.f(); //调用父类对象的普通方法
value = 200;
System.out.println("ChildClass.value="+value);
System.out.println(value);
System.out.println(super.value); //调用父类对象的成员变量
}
}
继承树追溯
属性/方法查找顺序:(比如:查找变量 h)
- 查找当前类中有没有属性 h
- 依次上溯每个父类,查看每个父类中是否有 h,直到 Object
- 如果没找到,则出现编译错误。
- 上面步骤,只要找到 h 变量,则这个过程终止。
构造方法调用顺序:
构造方法第一句总是:super(…)来调用父类对应的构造方法。所以,流程就是:先向上 追溯到 Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。
静态初始化块调用顺序,与构造方法调用顺序一样,不再重复。
继承条件下构造方法的执行过程
public class TestSuper02 {
public static void main(String[ ] args) {
System.out.println("开始创建一个ChildClass对象......");
new ChildClass2();
}
}
class FatherClass2 {
public FatherClass2() {
System.out.println("创建FatherClass");
}
}
class ChildClass2 extends FatherClass2 {
public ChildClass2() {
System.out.println("创建ChildClass");
}
}