引入:

在文章 11.面向对象的三大特征的最后案例中,父类Animal类的cure()方法,目的就是让子类去重写它,但是函数体中的代码毫无意义,不写又会报错(定义一个标准的函数需要有函数体)。那怎样才能不写函数体呢?下面我们来解决这个问题

public void cure{
}

一、抽象方法:

        如果一个方法,不需要实现体(函数内容),就可以声明抽象方法

1. 抽象方法:没有方法体的方法。java中使用abstract关键字声明的方法就是抽象方法。

2. 书写格式:
    访问修饰符 abstract 返回值类型 方法名称(参数列表);
    抽象方法必须定义在抽象类中。

public abstract class Animal{
        public abstract void cure();
}

抽象类中不一定有抽象方法!!!
                如果一个类继承了抽象类,就必须实现该类的抽象方法!!!

                如果一定不实现,则将这个子类继续声明抽象类。

//抽象类中不一定有抽象方法
public class Animal {    
     // 100
     private int health;
  
     public int getHealth() {//普通方法
         return health;
     }
  
     public void setHealth(int health) {//普通方法
         this.health = health;
     }}
// 如果一个类继承了抽象类,就必须实现该类的抽象方法
public class QQ extends Animial{
       
         @override
        public void cure(){
        }
}
       //如果一定不实现,则将这个子类继续声明抽象类。
public abstract class QQ extends Animial{
}

3. 抽象类:
    被abstract关键字修饰的类。

public abstract class Animal{
}

二、接口:

    接口,本质是特殊的类,特殊抽象类
    接口中所有方法都是没有实现的(抽象方法)。

在jdk8之前:
    接口中的所有属性和方法,默认都是public的!!!即便是你没有使用public关键字修饰。

    java中使用interface关键字来定义接口
    java中,接口可以多实现。

package com.openlab.day13.test02;

public interface MyInterface {
	
	// 所有方法都是没有实现的(抽象方法),jdk8之前
	
	public void say();
	
	int sum(int x, int y);
	
	public void sayHello();

}
package com.openlab.day13.test02;

public interface MyInterface02 {

	void show();
	
}

    接口的实现使用implements关键字实现接口
    子类一旦实现了接口,必须要实现接口所有的抽象方法,
    如果不想实现,则必须将该子类声明为抽象类。

package com.openlab.day13.test;

import com.openlab.day13.test02.MyInterface;
import com.openlab.day13.test02.MyInterface02;

public class Test02 implements MyInterface, MyInterface02 {

	@Override
	public void say() {
		System.out.println("test02实现了say方法");
	}

	@Override
	public int sum(int x, int y) {
		return x + y;
	}

	@Override
	public void sayHello() {
		System.out.println("test02实现了sayhello方法");
	}

	@Override
	public void show() {
		System.out.println("子类的show方法");
	}

}
package com.openlab.day13.test;

import com.openlab.day13.test02.MyInterface;
import com.openlab.day13.test02.MyInterface02;

public class Test {

	public static void main(String[] args) {
		
		MyInterface mi = new Test02();
		mi.say();
		mi.sayHell();
		System.out.println(mi.sum(10, 20));
		
	}
}

    接口也无法直接实例化,必须使用子类,以多态的形式完成实例化。

    注意:接口可以多实现!!

jdk8的接口新特性:
    允许接口存在默认方法和静态方法,非抽象方法

package com.openlab.day13.test02;

public interface MyInterface02 {

	void show();
	
	// 定义一个默认方法方法
	// 该方法主要的目的就是等待子类继承
	public default void test01() {
		System.out.println("定义在接口的方法");
	}
	
    // 定义一个静态方法方法
    //相当于把接口当作工具类使用
	public static int add(int a, int b) {
		return a + b;
	}
	
	
}
package com.openlab.day13.test;

import com.openlab.day13.test02.MyInterface;
import com.openlab.day13.test02.MyInterface02;

public class Test {

	public static void main(String[] args) {
	
		MyInterface02 mm = new Test02();
		mm.test01();
		
	}
}


接口与抽象类的区别(jdk8之前)


   1 相同点 :


        都位于继承的顶端, 用于被其他实现或继承 ;


        都不能实例化;


        都包含抽象方法,其子类都必须覆写这些抽象方法;


   2. 区别 :


        抽象类为部分方法提供实现, 避免子类重复实现这些方法 , 提供代码重用性 ; 接口只能包含抽象方


        法;


        一个类只能继承一个直接父类( 可能是抽象类 ), 却可以实现多个接口 ;( 接口弥补了 Java的单继承)


   3. 二者的选用 :


        优先选用接口, 尽量少用抽象类 ;


        需要定义子类的行为, 又要为子类提供共性功能时才选用抽象类