【JavaSE】六、抽象 接口 关键字

本文详细介绍了Java编程中的关键概念,包括main方法、抽象类与抽象方法、接口和设计模式。讲解了模板方法、代理模式以及工厂模式的应用,并探讨了静态成员和单例模式的实现。同时,文章还涵盖了类与接口之间的冲突处理,以及代理模式在实际场景中的应用。通过对这些基础知识的深入理解,有助于提升Java开发能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

main方法

程序入口,是一个普通的静态方法。可作为我们与控制台交互的方式

抽象类和抽象方法(abstract)

类的设计应该保证父类和子类能够共享特征,以至于其没有具体实例。这样的类就叫做抽象类

abstract可以用来修饰类【不能修饰final】、方法【不能修饰private、static、final】。

修饰类:

  • 此类不能实例化
  • 抽象类中必有构造器,便于子类实例化时调用
  • 开发中都会提供抽象类的子类,让子类对象实例化
  • 抽象类中可以没有抽象方法

修饰方法:

  • 抽象方法只有声明,没有方法体
public abstract void eat();
  • 包含抽象方法的类一定是一个抽象类
  • 若子类重写父类中的所有抽象方法后,子类方能实例化
  • 若子类没有重写父类中的所有抽象方法,则此子类是一个抽象类

抽象类的匿名子类

当Employee为抽象类时,可以创建一个匿名子类并new出对象

Employee employee=new Employee() {
						//重写Employee的抽象方法
            @Override
            public void work() {
                System.out.println("工作");
            }
        };

设计模式:模板方法(TemplateMethod)

当功能内部一部分实现是确定的,一部分是不确定的。此时可以把不确定的部分暴露出去让子类实现。

**abstract class Template{
    //计算某段代码执行所需花费的时间
    public void spendTime(){
        long start=System.currentTimeMillis();
        code();//不确定、易变的部分
        long end=System.currentTimeMillis();
        System.out.println("花费时间为"+(end-start));
    }
    public abstract void code();
}**

接口(interface)

继承:“是不是”;接口:“能不能”。不同类都具有的功能

  • 接口和类是并列的两个结构

  • 版本差异

    ≤JDK7:只能定义全局常量和抽象方法

    全局常量:public static final【可省略】

    抽象方发:public abstract【可省略】

    ≥JDK8:除了上述方法外,还能定义静态方法、默认方法

    interface Run{
        //静态方法【只能通过接口来调用Run.method1()】
        public static void method1(){
            System.out.println("静态方法");
        }
        //抽象方法
        public abstract void method2();
        //默认方法
        public default void method3(){
            System.out.println("默认方法");
        }
    }
    
  • 接口中不能定义构造器—>接口不能实例化

  • 开发中,接口通过让类实现(implements)来使用

    若实现类覆盖了接口中所有抽象方法则能被实例化

    否则此实现类仍为抽象类

  • 可以实现多个接口—>弥补了Java单继承的局限性

    class AA extends BB implements CC,DD,EE

  • 接口与接口之间可以多继承

  • 接口具体的使用,体现了多态性

  • 接口是一种规范【面向接口编程】

    使用不同数据库进行操作时代码不同。实际使用时,将接口定义为形参即可操作。具体代码各个数据库内部将接口进行实现即可。

  • 父类与接口冲突

    调用同名属性时,父类:super.x;接口:接口.x

    调用同名同参方法时,若未进行重写,默认调用父类方法

    调用重写后方法:method()

    调用父类方法:super.method()

    调用接口方法:接口.super.method()

  • 接口与接口冲突

    调用同名同参的默认方法时,出现接口冲突,报错

代理模式(Proxy)

为其他对象提供一种代理以控制对该对象的访问

被代理类完成核心功能

其余杂项及额外功能交予代理类做

例:接口star有面谈、签合同、订票、唱歌、收钱的抽象方法

implement Star{}

被代理类:歌星A实现接口,其中仅需完成核心功能唱歌

class RealStarA implements Star{}

代理类:实现接口的所有方法,其中唱歌方法通过调用被代理类的唱歌方法即可

class Proxy implements Star{}

当被代理类的对象歌星A被替换成歌星B,代理类无需修改,仅需将代理类歌星B的核心方法进行修改即可。

class RealStarB implements Star{}

在这里插入图片描述

public class Test {
    public static void main(String[] args) {
				//创建被代理类的对象server
        Server server=new Server();
				/*
				创建代理类的对象proxyServer
				将server赋给了proxyServer的netWork
				*/
        ProxyServer proxyServer=new ProxyServer(server);
        proxyServer.browse();
    }
}
interface NetWork{
    void browse();
}
//被代理类
class Server implements NetWork{
    @Override
    public void browse() {
        System.out.println("真实的服务器访问网络");
    }
}
//代理类
class ProxyServer implements NetWork{
    private NetWork netWork;
    public ProxyServer(NetWork netWork){
        this.netWork=netWork;
    }
    public void check(){
        System.out.println("联网前的检查工作");
    }
    @Override
    public void browse() {
        check();
        netWork.browse();
    }
}

应用场景

  • 安全代理:屏蔽对真实对象的直接访问
  • 远程代理:通过代理类处理远程方法调用(RMI)
  • 延迟加载:先加载轻量级的代理对象,真正需要时再加载真实对象
    • 开发一个大文档查看软件,其中有大的图片,打开文件时不可能显示所有图片,可以使用代理模式,先加载主要的东西,需要查看图片时,用proxy来进行大图片的打开
  • 静态代理(静态定义代理类)
  • 动态代理(动态生成代理类)
    • JDK自带的动态代理,需要反射等知识

工厂模式(Factory)

实现创建者与调用者的分离

简单工厂模式

新产品的加入要修改工厂的判断语句

class CarFactory{
    //方式一
    public static Car getCar(String type){
        if("奥迪".equals(type)){
            return new Audi();
        }
        else if("比亚迪".equals(type)){
            return new BYD();
        }
        else{
            return null;
        }
    }
    //方式二
    public static Car getAudi(){
        return new Audi();
    }
    public static Car getByd(){
        return new BYD();
    }
}

工厂方法模式

若要加新产品不需要修改原有代码,仅需添加一个工厂类和车辆类即可,但是工厂的具体角色写死了

interface Car{
    void run();
}
class Audi implements Car{
    @Override
    public void run() {
        System.out.println("奥迪run");
    }
}
class BYD implements Car{
    @Override
    public void run() {
        System.out.println("比亚迪run");
    }
}
interface CarFactory{
    Car getCar();
}
class AudiFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new Audi();
    }
}
class BydFactory implements CarFactory{
    @Override
    public Car getCar() {
        return new BYD();
    }
}

抽象工厂模式

与工厂模式的区别在于需要创建对象的复杂程度

静态(static)

可以用来修饰属性、方法、代码块、内部类。

修饰属性:静态变量(类变量)

  • 按是否使用static修饰,又分为静态属性v.s.非静态属性(实例变量)
    • 实例变量:创建了类的多个对象,每个对象独立拥有一套类的非静态属性
    • 静态变量:多个对象共享一个静态变量
  • 静态变量随着类的加载而加载(早于对象的创建)
  • 类只会加载一次,静态变量在内存中只会存在一份:在方法区的静态域中
  • 举例:System.out、Math.PI

修饰方法:静态方法

  • 静态方法不能重写
  • 静态方法中只能调用静态的方法/属性
  • 非静态方法中既可以调用静态方法/属性,也已调用非静态的方法/属性
  • 在静态的方法内,不能使用this、super关键字

设计模式:单例(Singleton)

设置某个类只能存在一个对象实例

  • 构造器访问权限设为private,因此不能在类的外部new出类的对象
  • 调用该类的静态方法返回类内部创建的对象
  • 静态方法只能访问静态变量,因此指向类内部产生的该类对象的变量也应该是静态的

饿汉式

class Bank{
    //1.私有化类的构造器
    private Bank(){

    }
    //2.内部创建类的对象
    //4.要求此对象也必须为static的
    private static Bank instance=new Bank();
    //3.提供公共方法返回类的对象
    public static Bank getInstance(){
        return instance;
    }
}

优:线程安全

劣:对象加载时间过长

懒汉式

class Bank{
    //1.私有化类的构造器
    private Bank(){

    }
    //2.声明当前类对象
    //4.此对象也必须为static的
    private static Bank instance=null;
    //3.声明public、static的返回当前类对象的方法
    public static Bank getInstance(){
        if(instance==null){
            instance=new Bank();
        }
        return instance;
    }
}

优:延迟对象创建

劣:线程不安全,需要加锁

方式一:效率稍差

public static Bank getInstance(){
        synchronized (Bank.class){
            if(instance==null){
                instance=new Bank();
            }
            return instance;
        }
    }

方式二:效率稍高

public static Bank getInstance(){
        if(instance==null){
            synchronized (Bank.class){
                if(instance==null){
                    instance=new Bank();
                }
            }
        }
        return instance;
    }

this

可以用来修饰属性、方法、构造器。理解为:当前对象

class Person{
    int age;
    String name;
    Person(){
        System.out.println("空构造器");
    }
    Person(int age){
        this();//调用空构造器
        System.out.println("带age的构造器");
    }
    Person(String name,int age){
        this(age);//调用带age的构造器
        System.out.println("带name和age的构造器");
    }
}

this(形参列表)必须声明在当前构造器的首行

构造器内部最多只能用一个this(形参列表)来调用其他构造器

super

显式调用父类中声明的属性或方法

属性和方法:当子类和父类中定义了同名的属性/方法,想要在子类中调用父类声明的属性/方法,必须显式使用“super.属性/方法”

构造器:

  • 必须在子类构造器的首行,this(形参列表)和super(形参列表)只能二选一
  • 当构造器首行没有显式声明this(形参列表)或super(形参列表),则默认调用父类空参构造器,也就是super()。

final

可以修饰类、方法、变量

  • 修饰类:此类不能被其他类锁继承 如:String类、System类、StringBuffer类
  • 修饰方法:此方法不能被重写 如:Object类中的getClass()
  • 修饰变量:常量
    • 修饰属性:可以赋值的位置有:显式初始化、代码块中初始化、构造器中初始化
    • 修饰局部变量:尤其是使用final修饰形参时,表明此形参是常量。调用此方法时,给常量形参赋一个实参,一旦赋值无法修改。
  • static final用来修饰属性:全局常量

package

为了更好的实现项目中类的管理,提供包的概念

使用package申明类或接口所属的包,声明在源文件的首行

包属于标识符,命名规范xxxyyyzzz

每”.”一次,代表一层文件目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值