1、抽象类

  (1)抽象类概述

只有子类应该包含的方法(没有方法体的方法),没有具体实现的类。方法体的实现交给抽象类的子类,子类根据具体需要去实现。任何带有抽象方法的类都为抽象类,他只是对问题的抽象表示,不能完整地表示一个事物,由于抽象类不能进行实例化,因此,必须由子类继承之后才能使用里面的方法。

(2)抽象类的定义和实现

定义一个形状抽象类:

public abstract class Shape {
    public int width;
    public int length;

    public Shape(int width, int length) {
        this.length = length;
        this.width = width;
    }

    public Shape() {

    }

    public abstract double area();
}

 定义Square类,继承抽象类,重写抽象方法:

public class Square extends Shape{

    public Square(int width,int length){
    super(width,length);
    }
    
    public double area() {
    return width*length;
    }

}

定义Circle类,继承抽象类,重写抽象方法:

public  class Circle extends Shape {
    public double radius;    
    public Circle(double radius){
        this.radius=radius;
    }
    public double area() {
     return radius*radius*Math.PI;
    }

}

测试类:

public class Test {
public static void main(String[] args) {
    Circle c=new Circle(1);
    System.out.println("圆的面积为"+c.area());
    Square s=new Square(1,2);
    System.out.println("长方形的面积为"+s.area());
}
}

结果:

抽象类和接口(抽象类、接口、抽象类和接口的异同)_抽象方法

(3)抽象类的特点

抽象类和方法都需要被abstract修饰。

抽象类不能创建对象,子类继承抽象类后可以实例化。

子类必须覆盖抽象类的所有抽象方发,否则,子类还是一个抽象类。

 

2、接口

接口是比抽象类更为抽象的类,interface关键字提供了一个完全抽象的类,包含了类要实现的方法。一个接口的实现类必须实现接口所描述的所有方法,否则就必须声明为抽象类。

(1)接口的特点

成员变量:必须是静态的,且必须要赋初值,该值不能再被修改。默认修饰符为:public static final

成员方法:为抽象的,public abstarct 可以省略,接口中不能有一般方法。

定义Shape接口:

interface Shape {
    public static final double pi = Math.PI;

    public abstract double getArea();

    public abstract double getL();
}

定义Circle类,实现Shape接口的功能:

public class Circle implements Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public double getArea() {
        return radius * radius * pi;
    }

    public double getL() {
        return 2 * pi * radius;
    }

}

定义Rectangle类,实现Shape接口的功能:

public class Rectangle implements Shape {
    private double width;
    private double Length;

    public Rectangle(double width, double Length) {
        this.width = width;
        this.Length = Length;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getLength() {
        return Length;
    }

    public void setLength(double length) {
        Length = length;
    }

    public double getArea() {
        return width * Length;

    }

    public double getL() {
        return 2 * (width + Length);
    }

}

定义测试类:

public class Test {
    public static void main(String[] args) {
        Circle c = new Circle(2);
        System.out.println("圆的面积为" + c.getArea());
        System.out.println("圆的周长为" + c.getL());

        Rectangle r = new Rectangle(1, 2);
        System.out.println("长方形的面积为" + r.getArea());
        System.out.println("长方形的周长为" + r.getL());

    }
}

运行结果:

抽象类和接口(抽象类、接口、抽象类和接口的异同)_子类_02

 (2)接口的继承

定义第一个接口Shape1:

interface Shape1 {
    public static final double pi = Math.PI;

    public abstract double getArea();

}

定义第二个接口Shape2:

interface Shape2 {
    public abstract double getL();
}

定义Circle类,实现接口Shape1和Shape2:

public class Circle implements Shape1, Shape2 {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public double getArea() {
        return radius * radius * pi;
    }

    public double getL() {
        return 2 * pi * radius;
    }

}

测试类:

public class Test {
    public static void main(String[] args) {
        Circle c = new Circle(2);
        System.out.println("圆的面积为" + c.getArea());
        System.out.println("圆的周长为" + c.getL());
    }
}

运行结果:

抽象类和接口(抽象类、接口、抽象类和接口的异同)_子类_03

(3)接口的好处

 实现多重继承。

 接口可以降低耦合性(功能能够重复利用)。

 

3、抽象类和接口的异同

不同点:

(1)抽象类可以有普通方法,而接口只能为抽象方法,不能有普通方法,但是JDK8以后接口中可以添加使用default或者static修饰的方法(default修饰方法只能在接口中使用,在接口中被default标记的方法为普通方法,可以直接写方法体),例如在Comparator接口中有如下default修饰的方法:

 default Comparator<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return (Comparator<T> & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }

(2)一个类可以实现多个接口,但是只能继承一个抽象类

抽象类和接口(抽象类、接口、抽象类和接口的异同)_抽象方法_04

 抽象类和接口(抽象类、接口、抽象类和接口的异同)_实例化_05

(3)关键字不同:抽象类的继承extends,接口的实现implements

(4)在需要降低代码冗余的时候采用抽象类,否则可以使用接口,面向接口编程能够降低代码的耦合度

(5)抽象类可以有构造⽅方法,接⼝口中不不能有构造⽅方法

(6)抽象类中的抽象⽅方法的访问类型可以是public,protected,但接⼝中的抽象方法只能是public类型的,并且默认即为public abstract类型。

(7)抽象类中可以包含静态方法,接⼝中不能包含静态方法。抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

相同点:

抽象类和接口都不能实例化

抽象类的子类或接口的实现类都必须都必须重写接口或抽象类的所有方法,才能够实例化。否则,该类仍然为抽象类。

 

4、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰

都不能。

抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。

本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。

synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

 

每个人都会有一段异常艰难的时光 。 生活的压力 , 工作的失意 , 学业的压力。 爱的惶惶不可终日。 挺过来的 ,人生就会豁然开朗。 挺不过来的 ,时间也会教你 ,怎么与它们握手言和 ,所以不必害怕的。 ——杨绛