- 如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错.所以呢,一般情况下,最好能为每个类提供一个无参构造方法,以便于对该类进行扩展,同时避免错误。
- 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则**必须显式的使用"super.属性"**的方式,表明调用的是父类中声明的属性。
- 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
public class Person {
private String name;
private int age;
private Date birthDate;
public Person(String name, int age, Date d) {
this.name = name;
this.age = age;
this.birthDate = d; }
public Person(String name, int age) {
this(name, age, null);
}
public Person(String name, Date d) {
this(name, 30, d);
}
public Person(String name) {
this(name, 30);
}
}
public class Student extends Person {
private String school;
public Student(String name, int age, String s) {
super(name, age);
school = s; }
public Student(String name, String s) {
super(name);
school = s; }
// 编译出错: no super(),系统无法调用父类无参数的构造器。
//There is no default constructor available in ‘chapter01.Person’
public Student(String s) {
school = s; }
}
2.2 构造方法链
在任何情况下,构造一个类的实例时,将会调用沿着继承链的所有父类的构造方法。当构造一个子类的对象时,子类构造方法会在完成自己的任务之前,首先调用它的父类的构造方法。如果父类继承自其他类,那么父类构造方法又会在完成自己的任务之前,调用它自己的父类的构造方法。这个过程持续到沿着这个继承体系结构的最后一个构造方法被调用为止。这就是构造方法链(constructor chaining)。
public class Faculty extends Employee {
public static void main(String[] args) {
Faculty faculty = new Faculty();
}
public Faculty() {
System.out.println(“(4) Performs Faculty’s tasks”);
}
}
class Employee extends Person {
public Employee() {
this(“(2)Invoke Employee’s overloaded constructor”);
System.out.println("(3)Performs Employee’s tasks ");
}
public Employee(String s) {
System.out.println(s);
}
}
class Person {
public Person() {
System.out.println(“(1) Performs Person’s tasks”);
}
}
结果:
在第3 行,new Faculty() 调用Faculty 的无参构造方法。由于 Faculty 是 Employee 的子类,所以,在Faculty 构造方法中的所有语句执行之前,先调用 Employee 的无参构造方法。Employee 的无参构造方法调用Employee 的第二个构造方法(第13 行)。由于 Employee 是 Person 的子类,所以,在 Employee 的第二个构造方法中所有语句执行之前,先调用 Person 的无参构造方法。
2.3 调用父类的方法
super.方法名(参数);
3.方法重写
子类从父类中继承方法。有时,子类需要修改父类中定义的方法的实现,这称作方法重 写(method overriding),:要重写一个方法,需要在子类中使用和父类一样的签名以及一样的返回值类型来对该方法进行定义。
注意以下几点:
- 仅当实例方法是可访问时,它才能被覆盖。因为私有方法在它的类本身以外是不能访问的,所以它不能被覆盖。如果子类中定义的方法在父类中是私有的,那么这两个方法完全没有关系。
- 子类不能用语法 super.super.toStringO 访问父类的父类中的toString ,这是一个语法错误。
- 与实例方法一样,静态方法也能被继承。但是,静态方法不能被覆盖。如果父类中定义的静态方法在子类中被重新定义,那么在父类中定义的静态方法将被隐藏。可以使用语法:父类名 .静态方法名(SuperClassName.staticMethodName) 调用隐藏的静态方法。
这个再次详细说明一下
public class StaticExtends {
public static void main(String[] args) {
//声明为Father类,son1静态方法和Father类绑定
Father son = new Son();
son.method();
son.staticMethod();
Son son2 = new Son();
son2.method();
son2.staticMethod();
}
}
class Father {
void method() {
System.out.println(“父类方法”);
}
static void staticMethod() {
System.out.println(“父类静态方法”);
}
}
class Son extends Father {
@Override
void method() {
System.out.println(“子类方法”);
}
static void staticMethod() {
System.out.println(“子类静态方法”);
}
}
输出结果:
在子类中重写父类的static方法,是不会报错的,编译也可以通过,但是在通过一个声明为父类,实际类型为子类的引用变量调用该方法时,发现被调用的仍是父类中原本以为会被覆盖的方法,不具有“多态”特性。所以呢,父类的static方法是不会被重写的。
4.Object类及其常用方法
Java 中的所有类都继承自 java.lang.Object 类,如果在定义一个类时没有指定继承性,那么这个类的父类就被默认为是 Object。
4.1 toString()方法
Object 类中toString()方法的默认实现是:
public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
}
调用一个对象的 toString() 会返回一个描述该对象的字符串。默认情况下,它*返回一个由该对象所属的类名、at 符号(@)以及该对象十六进制形式的内存地址组成的字符串。*这个信息不是很有用,所以重写。
- 像String、Date、File、包装类等都重写了Object类中的toString()方法。使得在调用对象的toString()时,返回"实体内容"信息。
- 可以根据需要在用户自定义类型中重写toString()方法。 如String 类重写了toString()方法,返回字符串的值。
s1=“hello”;
System.out.println(s1);//相当于System.out.println(s1.toString());
- 基本类型数据转换为String类型时,调用了对应包装类的toString()方法
int a=10;
System.out.println(“a=”+a);
4.2 equals()方法
Object 类中 equals 方法的默认实现是:
public boolean equals(Object obj) {
return (this obj);
}
说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体。
- 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
- 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们 就需要对Object类中的equals()进行重写。重写的原则:比较两个对象的实体内容是否相同
tips:==和equals的区别:
- 1 = 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型 就是比较内存地址
- 2 equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。
- 3 具体要看自定义类里有没有重写Object的equals方法来判断。
- 4 通常情况下,重写equals方法,会比较类中的相应属性是否都相等。
二. 多态
5.1 介绍
首先呢,我们知道继承关系使一个子类继承父类的特征,并且附加一些新特征。子类是它的父类的特殊化,每个子类的实例都是其父类的实例,但是反过来就不成立。例如:每个圆都是一个几何对象,但并非每个几何对象都是圆。因此,总可以将子类的实例传给需要父类型的参数。使用父类对象的地方都可以使用子类的对象。这就是通常所说的多态。简单来说,多态意味着父类型的变量可以引用子类型的对象。
5.2 动态绑定
我们都知道方法可以在父类中定义而在子类中重写。(方法可以在沿着继承链的多个类中实现。JVM 决定运行时调用哪个方法。)那么
最后
由于篇幅原因,就不多做展示了
[外链图片转存中…(img-gYWYuX1y-1714574042949)]
[外链图片转存中…(img-LkaKKdyj-1714574042949)]
[外链图片转存中…(img-GBEaLq4Y-1714574042949)]
[外链图片转存中…(img-W5TjzLzx-1714574042950)]
[外链图片转存中…(img-kRN9EFHU-1714574042950)]
由于篇幅原因,就不多做展示了