同理,子类可以继承父类的非 private 方法,为了验证这一点,我们来看下面这个示例。
public class Wanger { void write() { } private void privateWrite() { } public void publicWrite() { } protected void protectedWrite() { } }
父类 Wanger 定义了四种类型的方法,缺省的 write、私有的 privateWrite()、共有的 publicWrite()、受保护的 protectedWrite()。
在子类 Wangxiaoer 中定义一个 main 方法,并使用 new 关键字新建一个子类对象:
可以确认,除了私有的 privateWrite(),其他三种类型的方法都可以继承到。
不过,子类无法继承父类的构造方法。如果父类的构造方法是带有参数的,代码如下所示:
public class Wanger { int age; String name; public Wanger(int age, String name) { this.age = age; this.name = name; } }
则必须在子类的构造器中显式地通过 super 关键字进行调用,否则编译器将提示以下错误:
修复后的代码如下所示:
public class Wangxiaoer extends Wanger{ public Wangxiaoer(int age, String name) { super(age, name); } }
is-a 是继承的一个明显特征,就是说子类的对象引用类型可以是一个父类类型。
public class Wangxiaoer extends Wanger{ public static void main(String[] args) { Wanger wangxiaoer = new Wangxiaoer(); } }
同理,子接口的实现类的对象引用类型也可以是一个父接口类型。
public interface OneInterface extends Cloneable { } public class TestInterface implements OneInterface { public static void main(String[] args) { Cloneable c1 = new TestInterface(); } }
尽管一个类只能继承一个类,但一个类却可以实现多个接口,这一点,我在上一篇文章也提到过了。另外,还有一点我也提到了,就是 Java 8 之后,接口中可以定义 default 方法,这很方便,但也带来了新的问题:
如果一个类实现了多个接口,而这些接口中定义了相同签名的 default 方法,那么这个类就要重写该方法,否则编译无法通过。
FlyInterface 是一个会飞的接口,里面有一个签名为 sleep() 的默认方法:
public interface FlyInterface {
void fly();
default void sleep() {
System.out.println("睡着飞");
}
}
RunInterface 是一个会跑的接口,里面也有一个签名为 sleep() 的默认方法:
public interface RunInterface {
void run();
default void sleep() {
System.out.println("睡着跑");
}
}
Pig 类实现了 FlyInterface 和 RunInterface 两个接口,但这时候编译出错了。
原本,default 方法就是为实现该接口而不覆盖该方法的类提供默认实现的,现在,相同方法签名的 sleep() 方法把编译器搞懵逼了,只能重写了。
public class Pig implements FlyInterface, RunInterface { @Override public void fly() { System.out.println("会飞的猪"); } @Override public void sleep() { System.out.println("只能重写了"); } @Override public void run() { System.out.println("会跑的猪"); } }
类虽然不能继承多个类,但接口却可以继承多个接口,这一点,我不知道有没有触及到一些读者的知识盲区。
public interface WalkInterface extends FlyInterface,RunInterface{
void walk();
}
十二、this 关键字
在 Java 中,this 关键字指的是当前对象(它的方法正在被调用)的引用,能理解吧,各位亲?不理解的话,我们继续往下看。
看完再不明白,你过来捶爆我,我保证不还手,只要不打脸。
01、消除字段歧义
我敢赌一毛钱,所有的读者,不管男女老少,应该都知道这种用法,毕竟写构造方法的时候经常用啊。谁要不知道,过来,我给你发一毛钱红包,只要你脸皮够厚。
public class Writer {
private int age;
private String name;
public Writer(int age, String name) {
this.age = age;
this.name = name;
}
}
Writer 类有两个成员变量,分别是 age 和 name,在使用有参构造函数的时候,如果参数名和成员变量的名字相同,就需要使用 this 关键字消除歧义:this.age 是指成员变量,age 是指构造方法的参数。
02、引用类的其他构造方法
当一个类的构造方法有多个,并且它们之间有交集的话,就可以使用 this 关键字来调用不同的构造方法,从而减少代码量。
比如说,在无参构造方法中调用有参构造方法:
public class Writer {
private int age;
private String name;
public Writer(int age, String name) {
this.age = age;
this.name = name;
}
public Writer() {
this(18, "沉默王二");
}
}
也可以在有参构造方法中调用无参构造方法:
public class Writer {
private int age;
private String name;
public Writer(int age, String name) {
this();
this.age = age;
this.name = name;
}
public Writer() {
}
}
需要注意的是,this() 必须是构造方法中的第一条语句,否则就会报错。