抽象类和接口

本文详细介绍了Java中的抽象类和接口,包括它们的特点、实例、应用(如模板方法模式和代理模式),以及两者之间的异同,帮助读者理解这两种重要的编程工具。
摘要由CSDN通过智能技术生成

抽象类

1. 抽象类的特点

  • 关键字:abstract
  • 抽象类不能实例化
  • 抽象类有构造器
  • 抽象类只能单继承
  • 抽象方法只有方法的声明,没有方法体。

2. 抽象类的匿名子类

/**
 * 抽象类
 */
public abstract class  Person {
    public Person(){
        talk();
    }
    public abstract void talk();

}

/**
 * 匿名子类对象
 */
public class DemoTest01 {
    public static void getInstance(Person p){
        System.out.println(p);
    }

    public static void main(String[] args) {
        //方式一:
        Person p=new Person(){
            @Override
            public  void talk(){
                System.out.println("this is Overwrite talk method");
            }
        };

        //方式二:
        getInstance(new Person(){
            @Override
            public  void talk(){
                System.out.println("this is Overwrite talk method");
            }
        });
    }
}

3. 抽象类的应用:模板方法设计模式-TemplateMethod

案例1:计算某段代码执行,需要花费的时间

/**
 * 模板抽象类
 */
public abstract class TemplateTest {
    public void spendTime(){
        long startTime = System.currentTimeMillis();
        code();//不确定的部分。易变的部分。
        long endTime=System.currentTimeMillis();

        System.out.println("花费的时间是:" + (endTime-startTime));
    }

    /**
     * 需要子类重写的方法
     */
    public abstract void code();
}


public class SubTemplate extends  TemplateTest {
    @Override
    public void code() {
        //1000以内的质数
        for (int i = 2; i < 1000; i++) {
            boolean isFlag=true;
            for (int k = 2; k < Math.sqrt(i); k++) {
                if(i%k==0){
                    isFlag=false;
                    break;
                }
            }
            if(isFlag){
                System.out.println(i+" 是一个质数");
            }
        }
    }
}

//测试
public static void main(String[] args) {
    TemplateTest t1 = new Subtemplate();
    t1.spendTime();
}

案例2:银行办理不同的业务

public class TemplateMethodTest {

  public static void main(String[] args) {
    BankTemplateMethod btm = new DrawMoney();
    btm.process();

    BankTemplateMethod btm2 = new ManageMoney();
    btm2.process();
  }
}

/**
 * 模板抽象类
 */
abstract class BankTemplateMethod {
  // 具体方法
  public void takeNumber() {
    System.out.println("取号排队");
  }

  public abstract void transact(); // 办理具体的业务。钩子方法

  public void evaluate() {
    System.out.println("反馈评分");
  }

  // 模板方法,把基本操作组合到一起,子类一般不能重写
  public final void process() {
    this.takeNumber();

    this.transact();// 回调方法。像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码

    this.evaluate();
  }
}


class DrawMoney extends BankTemplateMethod {
  public void transact() {
    System.out.println("我要取款!!!");
  }
}

class ManageMoney extends BankTemplateMethod {
  public void transact() {
    System.out.println("我要理财!我这里有2000万美金!!");
  }
}

接口

1. 接口的特点

  • 关键字:interface
  • 接口中没有构造器
  • 接口可以继承多个接口。
  • 类可以实现多个接口。
  • 接口中的变量都是全局常量。
  • 接口中的方法,都是public修饰的。
  • 接口是一种规范。

2. 接口中的成员

  • 全局常量 public static final
  • 抽象方法 public abstract
  • 静态方法 public static
  • 默认方法 public default
  • 私有方法-Java9新特性

[1] 全局常量

public static final 数据类型 大写变量名;

[2] 抽象方法

public abstract 返回值类型 方法名( );

[3] 静态方法

public static 返回值类型 方法名( );

接口中的静态方法,只能通过接口调用。类似工具类。

[4] 默认方法

public default  返回值类型 方法名( );

  • 接口中的默认方法,可以通过实现类的对象来调用

  • 实现类可以重写接口的默认方法,调用的是重写后的方法

  • 如果接口和父类存在同名同参数的默认方法,默认调用的是父类中的方法

  • 如果实现了多个接口,多个接口中存在同名同参数的默认方法,并且父类中没有此同名同参数的默认方法,实现类必须重写该方法。

  • 调用父类中的方法: super.方法名( );

    调用子类自己重写的方法: this.方法名( );

    调用接口中的默认方法:接口名称.super.默认方法名( );

[5] 私有方法 - Java9新特性

将接口中重复的代码封装起来,只提供接口内部使用。

3. 解决接口冲突问题

子类实现了多个接口,并且多个接口中存在同名同参数的默认方法,父类中又没有此同名同参数的方法,子类如果没有重写此方法,编译会报错。引发接口冲突问题。

4. 接口的应用

代理模式 - Proxy

静态代理

针对某一个接口,提供的代理类。

案例1:访问网络

/**
 * 网络接口
 */
public interface NetWork {
    /**
     * 浏览网页
     */
    public abstract void browse();
}


/**
 * 被代理类
 */
public class Server implements NetWork {
    @Override
    public void browse() {
        System.out.println("服务器正在浏览");
    }
}


/**
 * 代理类
 */
public class ProxyServer implements NetWork {
    private NetWork netWork;

    public ProxyServer(NetWork netWork) {
        this.netWork = netWork;
    }

    /**
     * 连接网络校验
     */
    private void check(){
        System.out.println("连接网络之前的校验操作");
    }

    @Override
    public void browse() {
        check();
        netWork.browse();
    }
}


//测试
public static void main(String[] args) {
      NetWork netWork=new ProxyServer(new Server());
      netWork.browse();
  }
动态代理

JDK自带的动态代理。使用反射技术。
在代码执行过程中,动态生成代理类的对象。

工厂方法模式 - Factory

  • 创建者与调用者的分离
  • 用来生产同一等级结构中的固定产品。(支持增加任意产品)

案例1:生产汽车

汽车接口 和 实现的汽车接口的类

/**
 * 汽车种类的接口
 */
public interface Car {
    void run();
}

public class AuDi implements Car {
    @Override
    public void run() {
        System.out.println("奥迪正在跑...");
    }
}

public class BYD implements Car {
    @Override
    public void run() {
        System.out.println("比亚迪正在跑...");
    }
}

汽车工厂的接口 和 实现汽车工厂的类

/**
 * 生产汽车的接口
 */
public interface ProductCarFactory {
    Car getCar();
}

public class AuDiFactory implements ProductCarFactory {
    @Override
    public Car getCar() {
        return new AuDi();
    }
}


public class BYDFactory implements ProductCarFactory {
    @Override
    public Car getCar() {
        return new BYD();
    }
}

测试

public static void main(String[] args) {
    //从工厂中获取汽车的对象
    Car AuDi = new AuDiFactory().getCar();
    Car BYD = new BYDFactory().getCar();
    
    AuDi.run();
    BYD.run();
}

5. 接口的练习

/**
 * 比较大小的接口
 */
public interface CompareObject {

    /**
     * @param o
     * @return
     * 若返回值是 0 , 代表相等;
     * 若为正数,代表当前对象大;
     * 负数代表当前对象小
     */
    public int compareTo(Object o);
}

/**
 * 圆的类
 */
public class Circle {
    private Double radius;

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

    //get and set method...
}

/**
 * 继承圆,并实现比较大小接口的方法
 */
public class ComparableCircle extends Circle implements CompareObject {
    public ComparableCircle(Double radius) {
        super(radius);
    }

    @Override
    public int compareTo(Object o) {
        if(this==o){
            return 0;
        }

        if(o==null || !(o instanceof  Circle)){
            throw new RuntimeException("传入的数据类型不匹配。不是一个圆!");
        }
        Circle c=(Circle)o;
        return Double.compare(this.getRadius(),c.getRadius());
    }
}

//测试
public static void main(String[] args) {
    ComparableCircle c1 = new ComparableCircle(3.6);
    ComparableCircle c2 = new ComparableCircle(3.6);
    int result=c1.compareTo(c2);
    if(result>0){
        System.out.println("c1面积大");
    }else if(result==0){
        System.out.println("面积相等");
    }else{
        System.out.println("c2面积大");
    }
}

6. 抽象类和接口的异同

相同点:

  • 抽象类和接口都不能实例化
  • 都可以定义抽象方法

不同点:

  • 抽象类只能单继承,接口可以继承多个接口
  • 抽象类有构造器,子类创建对象时,会调用父类中的构造器。接口没有构造器
  • 抽象类是一种模板,接口是一种规范




  • 29
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值