一、继承
1.概念
把很多类的相同特征和行为进行抽取,用一个类来描述。让多个类和这个类产生一个关系。这样,多个类就可以省略很多代码。这个关系就是继承。java中用extends关键字表示。
2.继承的特点
1):java中只能单继承,没有多继承。
2):java可以有多重(层)继承。
3.继承的体系结构
1):概念:多个具体的对象,不断的向上抽取共享的内容,最终形成了一个体系。这个体系叫做继承体系。
2):继承体系的学习和使用原则:
a)学习顶层的内容。因为他是整个体系的共性内容。
b)创建子类使用。也就是使用底层的具体对象。
4.继承的好处:
1)继承的出现提高了代码的复用性。
2)继承的出现让类与类之间产生了关系,提供了多态的前提。
5.子父类中的成员关系
A:成员变量
在子类方法中使用一个变量时:
首先,在方法的局部变量中找这个变量,有则使用。
否则,在本类中找成员变量,有则使用。
否则,在父类中找成员变量,有则使用。
否则,报错。
B:成员方法
用子类对象使用一个方法时。
首先,在子类中找这个方法,有则使用。
否则,在父类中找这个方法,有则使用。
否则,报错。
6.重写和重载的区别?
重载:在同一类中。方法名相同,参数列表不同。重载可以改变返回类型。
重写:在不同类中(子父类中)。方法声明相同(返回类型,方法名,参数列表均相同)。
重写需要注意:
1)子类方法的访问权限要大于等于父类方法的访问权限。
2)静态只能重写静态。但是这种情况一般不会出现。
7.this和super的区别
this:代表本类对象的引用。
super:代表父类的存储空间。
8.final关键字(重点)
1)最终的意思,可以用于修饰类,方法,变量。
2)final修饰的类不能被继承。
3) final修饰的方法不能被重写。
4) final修饰的变量是一个常量。只能被赋值一次。
5)内部类只能访问被final修饰的局部变量。
程序示例:
<span style="font-size:14px;">class Person{ //定义一个父类Person
String name;
int age;
Person(String name,int age){
this.name =name;
this.age=age;
System.out.println("姓名: "+name+" 年龄: "+age);
}
//Person共有功能eat
public void eat(){
System.out.println("eat");
}
}
class Student extends Person{ //定义一个子类student继承Person
Student(String name,int age){
super(name,age); //super关键字表示父类,因为姓名和年龄在父类中进行了初始化动作,在这里可以直接调用
}
//Student特有功能study
void study(){
System.out.println("study");
}
//Student特有功能exam
void exam(){
System.out.println("exam");
}
}
public class PersonExtends1 {
public static void main(String[] args) {
Student stu=new Student("qiao",23);
stu.eat();
stu.study();
stu.exam();
}
}</span>
二、抽象类
1.概念
抽象就是从多个事物中将共性的,本质的内容抽取出来。
2.特点
1):抽象类和抽象方法都要用abstract进行修饰
2):抽象类不能被实例化
3):抽象类中不一定有抽象方法,但是,有抽象方法的类一定是抽象类。
3.抽象类中数据的特点
A:成员变量
抽象类中可以有变量,也可以有常量。
B:成员方法
抽象类中可以有抽象方法,也可以有非抽象方法。
C:构造方法
抽象类是一个类,所以,它有构造方法。 虽然本身不能实例化。但是可以给子类实例化使用。
4.抽象类中的问题
1):抽象类中是否有构造方法?能不能被实例化?如果不能,为什么有构造方法?
抽象类有构造方法。 抽象类不能被实例化。抽象类中的构造方法供子类实例化调用。
2):抽象关键字abstract不可以和哪些关键字共存?
a):private,私有内容子类继承不到,所以,不能重写。但是abstract修饰的方法,要求被重写。两者冲突。
b):final,final修饰的方法不能被重写。而abstract修饰的方法,要求被重写。两者冲突。
c):static假如一个抽象方法能通过static修饰,那么这个方法,就可以直接通过类名调用。而抽象方法是没有方法体的,这样的调用无意义。
3):抽象类中可不可以没有抽象方法?如果可以,这样的类有什么用吗?
抽象类可以没有抽象方法。抽象类中没有抽象方法的作用,只是为了不让别的类建立该抽象类对象。
程序示例:
<span style="font-size:14px;">abstract class Person{
//定义抽象方法run()
abstract void run();
}
class Student extends Person{
//实现抽象方法run()
void run(){
System.out.println("Run");
}
}
public class Abstract1 {
public static void main(String[] args) {
Student stu=new Student();//创建Student实例对象
stu.run();//调用Student的run()方法
}
}</span>
三、接口
1.概念
当一个类中的方法都是抽象的时候,java提供了另一种表示方式,叫接口。
用interface关键字表示。类与接口关系用implements表示。
2.接口的成员特点
A:成员变量
是常量,默认修饰 public static final
B:成员方法
都是抽象的,默认修饰 public abstract
3.关系
A:类与类的关系
是继承关系。类与类只能单继承,可以多重继承。
B:类和接口的关系
是实现关系。类在继承一个类的同时,可以多实现接口。
C:接口和接口的关系
是继承关系。接口可以多继承接口。
4.接口的特点
1):是对外暴露的规则
2):是功能的扩展
3):接口的出现降低耦合性。(耦合:类与类之间的关系、内聚:类完成功能的能力)
编程规范:低耦合,高内聚。
4):接口可以多实现。如:CPU和主板、笔记本的USB插口、插座
四.抽象类和接口的区别
1.语法层面上的区别
1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2.设计层面上的区别
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。
此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比
如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,继承是一个 "是不是"的关
系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比
如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。
2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简
单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只
需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更
新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了
变更,则所有实现这个接口的类都必须进行相应的改动。
下面看一个网上流传最广泛的例子:门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口
来定义这个抽象概念:
<span style="font-size:14px;">abstract class Door {
public abstract void open();
public abstract void close();
}</span>
但是现在如果我们需要门具有报警alarm( )的功能,那么该如何实现?下面提供两种思路:
1)将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能;
2)将这三个功能都放在接口里面,需要用到报警功能的类就需要实现这个接口中的open( )和close( ),也许这个类根本就不具备open( )和close( )
这两个功能,比如火灾报警器。
从这里可以看出, Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而
alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close
两种行为。再设计一个报警门继承Door类和实现Alarm接口。
<span style="font-size:14px;">interface Alram {
void alarm();
}
abstract class Door {
void open();
void close();
}
class AlarmDoor extends Door implements Alarm {
void oepn() {
//....
}
void close() {
//....
}
void alarm() {
//....
}
}</span>