Java|菜鸟教程 https://www.runoob.com/java/java-inheritance.html
类、抽象类、接口、继承、实现
类的修饰符可以有——访问修饰符:public对所有类可见、 protected对同一包内的类和所有子类可见、 default(即默认,什么也不写): 在同一包内可见,不使用任何修饰符。
——非访问修饰符:static、 final、 abstract
抽象类的定义是: abstract class
public abstract class 抽象类名称{ ... }
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。
如果你想实现一个方法,这个方法能够在不同子类中实现不同的方法内容。可以在父类定义抽象方法,用abstract关键字修饰方法,方法后面不添加大括号直接用分号结束(例如 public abstract double Compute();)。如果父类有抽象方法,子类必须对这个抽象方法进行重写,除非这个子类依然是一个抽象类。注意,构造方法和static修饰的方法不能定义为抽象方法。抽象类中可以没有抽象方法,当时有抽象方法的只能是抽象类。
接口的修饰符:public和abstract
接口中的成员变量只能是 public static final 类型的。
接口中的方法会指定为 public abstract
public interface 接口名称 [extends 其他的接口名] {
// 声明变量 // 抽象方法
}
顺便一提:1、synchronized 和 volatile也是修饰符,用于线程。2、标记接口在文末提了一下
抽象类和接口的区别
- 1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
接口与类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
继承extends
请注意以下方法继承的规则:
- 子类拥有父类所有非private的方法和属性
- 子类的修饰符必须能涵盖父类,大于等于的关系。
父类中声明为 public 的方法在子类中也必须为 public。
父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
父类中声明为 private 的方法,不能够被继承。
- 同理,子类的返回值类型需要在父类的范围之内
- 父类在不同的包下,需要import父类所在的包
- 可以用super关键字访问父类的成员,用来引用当前对象的父类;this指向自己的引用
- 定义为final的类不能被继承
- 关于构造器。子类默认拥有父类的属性和方法,所以子类在被定义出来之前会先初始化他的父类。构造器是用来初始化一个类的。所以父类的构造器在子类的构造器之前调用。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。如果父类的构造器没有参数,那我们不需要在子类的构造器中显示调用,系统会自动为我们调用。
实例
class SuperClass { private int n; SuperClass(){ System.out.println("SuperClass()"); } SuperClass(int n) { System.out.println("SuperClass(int n)"); this.n = n; } } // SubClass 类继承 class SubClass extends SuperClass{ private int n; SubClass(){ // 自动调用父类的无参数构造器 System.out.println("SubClass"); } public SubClass(int n){ super(300); // 调用父类中带有参数的构造器 System.out.println("SubClass(int n):"+n); this.n = n; } } // SubClass2 类继承 class SubClass2 extends SuperClass{ private int n; SubClass2(){ super(300); // 调用父类中带有参数的构造器 System.out.println("SubClass2"); } public SubClass2(int n){ // 自动调用父类的无参数构造器 System.out.println("SubClass2(int n):"+n); this.n = n; } } public class TestSuperSub{ public static void main (String args[]){ System.out.println("------SubClass 类继承------"); SubClass sc1 = new SubClass(); SubClass sc2 = new SubClass(100); System.out.println("------SubClass2 类继承------"); SubClass2 sc3 = new SubClass2(); SubClass2 sc4 = new SubClass2(200); } }
实现implements
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
重写接口中声明的方法时,需要注意以下规则:
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
在实现接口的时候,也要注意一些规则:
- 一个类可以同时实现多个接口。
- 一个类只能继承一个类,但是能实现多个接口。
- 一个接口能继承另一个接口,且只能继承一个,这和类之间的继承比较相似。
标记接口
最常用的继承接口是没有包含任何方法的接口。
标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。
标记接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。
例如:java.awt.event 包中的 MouseListener 接口继承的 java.util.EventListener 接口定义如下:
package java.util; public interface EventListener {}
没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:
- 建立一个公共的父接口:
正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。
- 向一个类添加数据类型:
这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。