抽象类和接口

抽象类和接口,第1张

抽象类和接口 抽象类 抽象类概念

◼ Java类可定义一些不含方法体的方法,它的实现交给子类根据自己的情况去 实现,这样的方法就是抽象方法,包含抽象方法的类叫抽象类

◼ 抽象关键字:abstract

◼ 抽象类只是一个类型的部分实现,所以不能被实例化(不能new对象) (那有啥用?)

◼ abstract不能用于static方法或者构造函数,也不能与private、final共同修饰 同一个方法 (想想)

抽象类示例

抽象类示例2 (带构造函数的抽象类)

抽象类Animal:

◼ 公有属性:animalName(String)

◼ 2个构造函数:Animal()、Animal(String)

◼ 抽象方法:eat()

子类: Dog和Cat类

◼ 各自都有构造函数: Dog()/Dog(String)、Cat()/Cat(String)

◼ 各自实现抽象方法:eat()

◼ 分别输出: "某某狗吃骨头!", "某某猫吃老鼠!"

测试类

public class Test {
    public static void main(String args[]) {
		//Animal a = new Animal(); //报错
        Animal a = new Dog("哈士奇");
		//Animal a = new Cat("大橘");
        a.eat();
    }
}
抽象类特点归纳

◼ 含有抽象方法的类必须被声明为抽象类。但抽象类中不一定包含的都是抽象方法

◼ 抽象类可以有构造方法,但构造方法不能声明为抽象★

◼ 抽象类提供一个类型的部分实现,所以不能被实例化(即不能用new去产生对象), 但可声明对象(用于多态) ★

◼ 抽象类不能用final来修饰,即一个类不能既是最终类又是抽象类

◼ 抽象类的子类必须重写所有抽象方法后才能被实例化,否则子类还是个抽象类

◼ 抽象方法只需声明,而不需实现

◼ abstract不能与private、static、final并列修饰同一个方法

 

接口 1. 接口概念

接口是一种特殊的抽象类:

◼ 如果一个抽象类中的所有方法都是抽象的,这个类就定义为接口 (interface)

◼ 接口的所有方法通常由子类全部实现 (是implements而非extends),不同子类的 实现可以具有不同的功能

◼ 如果一个类没有全部实现某个接口的所有方法,则这个类必须声 明为抽象的

接口示例

定义Shape接口,包含两个抽象方法:

◼ double getPerimeter(); //求周长

◼ double getArea(); //求面积

两个实现类:

◼ 矩形类(Rectangle)和圆(Circle)类

◼ 有自有属性,能求周长和面积

Shape接口

public interface Shape {
	public abstract double getPerimeter(); //求周长
	public abstract double getArea(); //求面积
}
其中public abstract可省略不写,即接口内方法默认是公有、抽象的

Rectangle类

class Rectangle implements Shape { //implements实现接口
    private double height;
    private double width;
    public Rectangle(double height,double width) {
        this.height = height;
        this.width = width;
    }
    @Override
    public double getPerimeter() {	//实现接口方法
        return 2 * (height + width);
    }
    @Override
    public double getArea() {//实现接口方法
        return height * width;
    }
}

Circle类

class Circle implements Shape {//implements实现接口
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }
    @Override
    public double getPerimeter() {//实现接口方法
        return 2 * Math.PI * radius;
    }
    @Override
    public double getArea() {//实现接口方法
        return Math.PI * radius * radius;
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        Shape r = new Rectangle(10,10);	//多态体现	
		// Shape r=new Circle(10);		//多态体现	
        System.out.println("矩形面积="+ r.getArea() );
        System.out.println("矩形周长="+ r.getPerimeter() );
    }
}
//Shape s = new Shape(); × 接口不能被实例化
2. 接口常量

◼ 接口中不能有变量,但可有常量

◼ 常量默认是 public static final 类型(公有全局静态常量),且必须被 显示初始化。

为什么不能定义变量:由于接口中的方法都是抽象的,如果接口可以定义变量,那么在接口中 无法通过行为(方法)来修改属性。

为什么是public static:接口提供的是一种统一的"协议",接口中的属性也属于"协议"成员,所 有实现类都可以共享这一"协议"。

为什么是final:实现接口的对象如果修改了接口中的属性,那么所有对象也都会自动拥有这一 改变后的值,这和接口提供的统一的抽象这种思想相抵触。

接口常量示例

接口常量调用方法:接口名.常量

public interface A {
    public static final int END=0; // OK 标准写法
    private final int OK=1; // × 不能为private
    int a; // × 没有初始化属于变量,接口不能有变量
    int b=1; // OK 初始化的变量会自动被识别为public static final常量
    public final int NO=-1; // OK 不写也默认是static
    static int share=0; // OK 不写也默认是public、final
}
//建议后三行public static final都写全
接口常量用法

3. 接口default/static方法

◼ Java 8 以后,接口可添加 default 或者 static 方法 (有实现的)

static方法:实现接口的类或者子接口不会继承(不能重写),用接口.方法名()调用
default方法:实现接口的类可以继承,可以选择重写 (注:多接口实现如有同名default方法则必须重写)
接口default方法
public interface A {
    public default void foo(){		//default不能省略
        System.out.println("这是default方法");
    }
}
class B implements A {
    public void foo() {		//实现类可以继承default方法或根据需要重写 (重写时不加default)
        System.out.println("重写default方法");
    }
}
class Test {
    public static void main(String[] args) {
        A a = new B();
        a.foo(); // 多态,输出 重写default方法
    }
}

接口static方法
public interface A {
    public static void a(){		//static不能省略
        System.out.println("这是A");
    }
}
public class B implements A {	//实现类不会继承static方法(不能重写)
}
public class test {
    public static void main(String[] args) {
        A a = new B();
        a.a(); // ×		//实现类不会继承接口中的 static 方法
        A.a(); // 正确调用
    }
}
4. 多接口

◼ Java一个类可以实现多个接口,从而间接的实现多继承

interface A {
    double fun1();
}
    Interface B {
        double fun2();
        }
class C implements A , B {
    public double fun1() {
//实现方法
    }
    public double fun2() {
//实现方法
    }
}

多接口编程

◼ 将Shape接口用多接口实现

Rectangle类实现多接口

class Rectangle implements Shape1, Shape2 {			//实现多接口
    private double height;
    private double width;
    public Rectangle(double height,double width) {
        this.height = height;
        this.width = width;
    }
    @Override
    public double getArea() {		//实现shape1接口的所有方法
        return height * width;
    }
    @Override
    public double getPerimeter() {		//实现shape2接口的所有方法
        return 2 * (height + width);
    }
}

Circle类实现多接口

class Circle implements Shape1, Shape2 {
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
    @Override
    public double getPerimeter() {
        return 2 * Math.PI * radius;
    }
}

5. 接口继承多接口

Java类只支持单继承,不支持多继承 但接口可以继承多个其他接口

public interface A {
    void fa();
}
public interface B {
    void fb();
}
public interface C extends A, B {
    void fc();
}
public class E implements C {
…//必须实现接口(包括父接口)所有的方法,如fa()、fb()、fc()
}

6. 接口的特点总结

◼ 接口中的方法默认都是 public abstract 类型(可省略),没有方法体

◼ 接口不能有构造函数,不能被实例化 (注:抽象类可以有构造函数)

◼ 接口中不能有变量,常量默认是 public static final,必须被显示初始化

◼ 接口中不能包含静态抽象方法,可以有default 或者 static 方法 (Java 8以后)

示例

public interface A {
    int var=1; // OK,实际是public static final常量
    public A() { } // 报错,接口不能有构造函数
    void method1() { } // 报错,接口抽象方法没有方法体
    protected void method2(); // 报错,接口方法必须是public abstract
    static void method3(); // 报错,接口不能包含静态抽象方法
    static void method4() { } // OK,接口可以包含静态方法,此方法可以有方法体
    default void method5() { } // OK,接口可以包含default方法
}

◼ 当一个类实现某个接口时,它必须重写这个接口的所有抽象方法(包括这个接口的父接口中的方法),否则这个类必须声明为抽象的

◼ 一个类可以实现多个接口

class C implements A , B { … }

◼ 一个接口可继承多个其它的接口 ★

interface C extends A, B { … }

◼ 一个接口不能实现(implements)另一个接口:

interface a implements b{ … } //错,接口不能实现接口

◼ 一个类在继承一个父类的同时,可实现一个或多个接口,但extends关键字必 须位于implements关键字之前:

public class A extends B implements C, D {...}

◼ 不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变 量引用实现了这个接口的类的实例(多态)

抽象类和接口对比

 

匿名类

◼ 匿名类:是指没有类名的内部类,必须在创建时使用 new 语句来声 明类(编译成功后还是会安排一个特殊名字)

◼ 语法形式如下:

new 类或接口() {		//可以是普通类、抽象类或接口
	// 类的主体 通常是重写父类方法或实现接口方法
};

匿名类特点

◼ 匿名类总是一个内部类,并且不能是static的

◼ 匿名类不能是抽象的,必须要实现继承的类或者实现的接口的所有抽象方法

◼ 匿名类总是隐式的final

◼ 匿名内部类中是不能定义构造函数的

◼ 匿名内部类中不能存在静态成员变量和静态方法(静态常量可以有 static final)

◼ 匿名类的class文件命名是:主类+$+1,2,3....

◼ 普通内部类的class文件命名是:主类+$+内部类名

 

Lambda表达式

◼ Lambda 表达式是一个匿名函数(也称为箭头函数)

◼ Lambda语法格式:

(类型 参数) ‐> { 代码语句; }

(int a, int b) -> {
int c = a + b;
return c;
}

//进一步省略
(a, b) -> a + b

Lambda表达式示例
() -> 5 // 无参数,返回值为 5 return都被省略
(int x, int y) -> x + y // 2个int参数,返回和
(x, y) -> x – y // 2个参数(数字),返回差值
x -> 2 * x // 接收一个参数(数字),返回其2倍 x仅仅是一个形参名
(String s) -> System.out.print(s) // String参数,只输出,无返回值

 

函数式接口

◼ 函数式接口:有且只有一个抽象方法的接口

◼ @FunctionalInterface注解:当接口中声明的抽象方法多于或少于一 个时就会报错

@FunctionalInterface
interface Person{
    void speak;
    void eat;
}//报错 多于一个
函数式接口的匿名类实现
@FunctionalInterface
interface Person {
void speak();
}
public class Test {
    public static void main(String[] args) {
        Person p = new Person() {
            @Override
            public void speak() {
                System.out.println("boy");
            }
        };
        p.speak();
    }
}

函数式接口的Lambda表达式实现
public class Test {
    public static void main(String[] args) {
        Person p = ()->System.out.println("boy") ;
        p.speak();
    }
}

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5608020.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)