Java抽象类和接口
抽象类
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类,使用abstract
关键字来定义抽象类。
-
abstract
除了可以修饰类之外还可以修饰方法。 -
abstract
不能用来修饰属性和构造器。 -
abstract
不能用来修饰私有方法和静态方法。 -
抽象类中一定有构造器,便于子类实例化时调用。
-
抽象方法只有方法的声明,没有方法体。
-
包含抽象方法的类,一定是抽象类。
-
子类重写了父类所有的抽象方法后,子类才能实例化,如果子类不重写父类所有的抽象方法,则子类也必须是抽象类。
public class AbstractTest1 {
public static void main(String[] args) {
//Person类使用abstract修饰,不可被实例化
// Person person = new Person();
}
}
//使用abstract修饰,此类不能被实例化
abstract class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//抽象方法
public abstract void eat();
public void walk() {
System.out.println("人走路");
}
}
class Student extends Person {
public Student(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("学生要吃点好的");
}
}
抽象类的匿名子类对象:
public class AbstractTest1 {
public static void main(String[] args) {
//创建了匿名子类的对象
Person p = new Person() {
@Override
public void eat() {
System.out.println("吃东西");
}
@Override
public void walk() {
System.out.println("走路");
}
};
}
}
//使用abstract修饰,此类不能被实例化
abstract class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//抽象方法
public abstract void eat();
public abstract void walk();
}
接口
有些情况下,必须从几个类中派生出一个子类,继承他们所有的属性和方法,但是Java不支持多继承,有了接口就可以实现多重继承的效果。使用 Interface关键字用来声明一个接口。
如何定义接口:定义接口中的成员
- JDK7及之前:只能定义全局常量和抽象方法
- 全局常量:public static final,书写时可以不写
- 抽象方法:public abstract
- JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法和默认方法
接口的特点
- 接口中不能定义构造器,意味着接口不能实例化。
- 接口通过让类去实现(implements)的方式来使用。
- 如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
- 如果实现类没有覆盖接口中所有的抽象方法,则此实现类必须仍是一个抽象类
示例:
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED); //7900
System.out.println(Flyable.MIN_SPEED); //1
Plane plane = new Plane();
plane.fly();
}
}
interface Flyable {
//全局常量
public static final int MAX_SPEED = 7900;
//省略 public static final
int MIN_SPEED = 1;
//抽象方法
public abstract void fly();
//省略public abstract
void stop();
}
class Plane implements Flyable {
@Override
public void fly() {
System.out.println("起飞");
}
@Override
public void stop() {
System.out.println("减速停止");
}
}
//没有覆盖接口中所有的抽象方法,则必须声明为抽象类
abstract class Kite implements Flyable {
@Override
public void fly() {
}
}
实现多个接口来弥补单继承的局限性
class AA extends BB implements CC,DD,EE
示例:
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED); //7900
System.out.println(Flyable.MIN_SPEED); //1
}
}
interface Flyable {
//全局常量
public static final int MAX_SPEED = 7900;
//省略 public static final
int MIN_SPEED = 1;
//抽象方法
public abstract void fly();
//省略public abstract
void stop();
}
interface Attackable{
void attack();
}
class Bullet extends Object implements Flyable,Attackable{
@Override
public void fly() {
}
@Override
public void stop() {
}
@Override
public void attack() {
}
}
接口和接口之间可以多继承
interface AA {
void method1();
}
interface BB {
void method1();
}
interface CC extends AA, BB {
}
接口可以看做是一种规范
public class USBTest {
public static void main(String[] args) {
Computer computer = new Computer();
//1.创建了接口的非匿名实现类的非匿名对象
Flash flash = new Flash();
computer.transferData(flash);
//2.创建了接口的非匿名实现类的匿名对象
computer.transferData(new Printer());
//3.创建了接口的匿名实现类的非匿名对象
USB phone = new USB() {
@Override
public void start() {
System.out.println("手机开始工作");
}
@Override
public void stop() {
System.out.println("手机结束工作");
}
};
computer.transferData(phone);
//4.创建了接口的匿名实现类的匿名对象
computer.transferData(new USB() {
@Override
public void start() {
System.out.println("mp3开始工作");
}
@Override
public void stop() {
System.out.println("mp3结束工作");
}
});
}
}
class Computer {
public void transferData(USB usb) {
usb.start();
System.out.println("具体传输数据的细节!");
usb.stop();
}
}
interface USB {
void start();
void stop();
}
class Flash implements USB {
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘结束工作");
}
}
class Printer implements USB {
@Override
public void start() {
System.out.println("打印机开启工作");
}
@Override
public void stop() {
System.out.println("打印机结束工作");
}
}
Java8接口的新特性
Java8中可以为接口添加静态方法和默认方法。
- 静态方法:使用static修饰,可以通过接口直接调用静态方法。
- 默认方法:默认方法使用default关键字修饰,可以通过实现类对象来调用。
定义接口:
/**
* JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
*/
public interface CompareA {
//静态方法
public static void method1() {
System.out.println("CompareA:北京");
}
//默认方法
public default void method2() {
System.out.println("compareA:上海");
}
default void method3() {
System.out.println("compareA:上海");
}
}
定义接口的实现类:
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
//接口中定义的静态方法,只能通过接口来调用
CompareA.method1(); //CompareA:北京
//通过实现类的对象,可以调用接口中的默认方法
//如果实现类重写了接口的默认方法,调用的则是重写后的方法。
s.method2(); //SubClass:上海
//如果子类继承的父类和实现的接口中声明了同名同参数的方法
//那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。类优先原则。
s.method3(); //SuperClass:北京
}
}
class SubClass extends SuperClass implements CompareA {
public void method2() {
System.out.println("SubClass:上海");
}
}
class SuperClass {
public void method3() {
System.out.println("SuperClass:北京");
}
}