抽象类和接口
14. 抽象类
-
抽象类为什么无法实例化,无法创建对象?
抽象类是类和类之间有共同特征,将这些具有共同特征的类再进一步抽象形成了抽象类。由于类本身是不存在的,所以抽象类无法创建对象。
-
抽象类属于引用数据类型
-
final和abstract不能联合使用,这两个关键字对立
-
abstract修饰符可以用来修饰方法也可以修饰类。如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
特点:没有方法体,以分号结尾,前面修饰符列表中有abstract关键字
//抽象类 public abstract class Person{ //抽象方法,只有名字没有方法体,由子类实现 public abstract void run(); } class Student extends Person{ //单继承,接口可以多实现 @Override public void run() { System.out.println("run"); } }
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
-
抽象类是无法实例化的,不能由new关键字来创建对象,它是用来让子类继承的,但它仍存在构造器,因为子类创建对象时,会通过super()调用父类构造方法
-
抽象类仍可以使用多态
public class Demo{ public static void main(String[] args){ Animal a = new Cat(); a.move(); } } abstract class Animal{ public abstract void move(); } class Cat extends Animal{ public void move(){ System.out.println("move"); } }
-
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
//抽象类 public abstract class Person{ public abstract void run(); } //子类也是抽象类 可以不实现父抽象类的方法 public abstract class Student extends Person{ }
-
面试题
Java语言中凡是没有方法体的方法都是抽象方法吗?
不对,Object类中有很多方法都没有方法体,都是以“;”结尾,但他们都不是抽象方法,例如:
public native int hashCode();
这个方法底层调用了C++写的动态链接库程序
15. 接口
声明类的关键字是class,声明接口的关键字是interface,接口是一种引用类型
-
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范(抽象方法),自己无法写方法,约束和实现分离
-
接口的本质是契约,就像我们社会的法律一样,制定好后大家都要遵守
-
接口是完全抽象的,抽象类是半抽象的
-
接口都需要有实现类,接口中只包含常量和抽象方法,接口中的方法定义其实都是抽象的public,常量定义都是public static final
package com.bobo.base; public interface Person{ public static final int age=9; //int age=9; //接口中的所有方法定义其实都是抽象的public public abstract void run(String name); void go(String name); } public class PersonImpl implements Person{ @Override public void run(String name) { } @Override public void go(String name) { } }
-
接口之间通过extends可以实现多继承
interface X{ } interface Y{ } interface Z extends X,Y{ }
-
一个类可以通过implements可以实现多个接口,只需要重写所有接口的方法即可,记得要加上publc,否则默认为default,违背了重写访问权限不能缩小的原则
public interface Person{ public static final int age=9; //接口中的所有方法定义其实都是抽象的public public abstract void run(String name); void go(String name); } public interface Teacher { void time(); } //实现多个接口 public class PersonImpl implements Person,Teacher{ @Override public void run(String name) { //public } @Override public void time() { } @Override public void go(String name) { } }
-
当继承和实现都存在时,extends关键字在前,implements关键字在后
class A extends B implements C{ //... }
-
接口不能被实例化,接口中没有构造方法,但接口依然可以使用多态,可以把接口想象为父类
public class Demo implements Student{ public static void main(String[] args) { Student s = new Demo(); //多态 s.run(); //调用接口里面的方法(面向接口编程) } @Override public void run() { System.out.println("跑步"); } } public interface Student { void run(); }
-
接口间也可以进行转型,最好是都被一个类实现时转型,否则需要使用instanceof,容易报错,了解即可
public class Demo implements A,B{ public static void main(String[] args) { A a = new Demo(); a.go(); B b = (B)a; //转型 b.run(); } @Override public void go() { System.out.println("A"); } @Override public void run() { System.out.println("B"); } } public interface A { void go(); } public interface B { void run(); }
-
从Java 8开始允许在接口中定义静态方法。在接口实现类中,通过接口名称直接调用静态方法
public static 返回值类型 方法名称(参数列表) { 方法体 }
-
从Java 8开始接口中也允许定义默认(default)方法,通过接口实现类创建对象调用
public default 返回值类型 方法名称(参数列表) { 方法体 }
-
总结
任何一个接口都有调用者和实现者。接口可以将调用者和实现者解耦合。调用者面向接口调用,实现者面向接口编写实现。
以后进行大项目开发时,就是将项目分离成一个一个模块,模块与模块之间采用接口衔接,降低耦合度
-
类型和类型之间的关系
“is a” ,”has a" , “like a”
-
"is a"
Cat is a Animal
凡是能满足is a的表示继承关系
A extends B
-
"has a"
I has a pen
凡是满足has a的表示关联关系,关联关系通常以属性的形式存在
A{ B b; }
-
"like a"
Cook like a FoodMenu
凡是能满足like a的表示实现关系,实现关系通常是类实现接口
A implements B
-
-
抽象类与接口的区别
- 抽象类是半抽象的,接口是完全抽象的
- 抽象类中有构造方法,接口 中没有构造方法
- 接口与接口之间支持多继承,类与类之间只能单继承
- 一个类可以同时实现多个接口,一个抽象类只能继承一个类
- 接口中只允许出现常量和抽象方法
以后开发中,使用接口更多一些没借口一般都是对“行为”的抽象