Java中的抽象类、接口、设计模式、包装类和泛型(附带相关面试题)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 一.抽象类(abstract),二.接口(interface),三.设计模式,四.包装类,五.泛型

一.抽象类(abstract)

abstract class className{ }

1.抽象类就是一个一些事务的具体抽象,比如说狗,猫,兔子等等可以往上抽象成同一个概念,即是动物的这个抽象类,因为都有着差不多的行为逻辑,所以抽象类中可以有吃,睡等共同方法

2.由于抽象类无法直接进行实例化,所以需要通过实例化子类实现向上转型,但是如果抽象类中有着static方法,则可以直接调用其方法而不需要实例化

3.必须有子类继承抽象类,而final类没有子类,所以抽象类不能是final类

4.抽象类中有多种方法可以使用,有普通方法,static方法,还有抽象方法

5.子类继承抽象类时候必须实现父类中的抽象方法

6.子类继承抽象类只能继承一个即所谓的单继承限制

7.如果抽象类中有构造函数则需要子类在继承的时候通过super()函数

案例代码:创建一个万物动物类与多个具体动物类

package Example91;
abstract class Animal {
    public abstract void shout();
    public abstract void eat();//抽象方法
    public void test() {
        System.out.println("一般方法");
    }
    public static Dog dogReturn() {
        return new Dog(); //static方法 无需实例化
    }
}
class Dog extends Animal {
    @Override //覆写抽象类中抽象函数
    public void shout() {
        System.out.println("汪汪汪");
    }
    @Override
    public void eat() {
        System.out.println("嗨嗨嗨,我吃吃吃吃吃");
    }
}
class Cat extends Animal {
    @Override //覆写抽象类中抽象函数
    public void shout() {
        System.out.println("喵喵喵");
    }
    @Override
    public void eat() {
        System.out.println("亚斯啦嘞");
    }
}
public class javaDemo {
    public static void main(String[] args) {
        Animal animal = new Cat();//通过向上转型实例化抽象类
        Animal animal1 = Animal.dogReturn();//无需实例化直接调用static方法
        animal.shout();
        animal1.shout();
    }
}

image.gifimage.gif*面试题: 普通类和抽象类有哪些区别?

抽象类不能被实例化;

抽象类可以有抽象方法,只需申明,无须实现;

有抽象方法的类一定是抽象类;

抽象类的子类必须实现抽象类中的所有抽象方法,否则子类仍然是抽象类;

抽象方法不能声明为静态、不能被static、final修饰。(注意是抽象方法,普通方法没限制)

二.接口(interface)

interface interfaceName { }

接口的抽象要大于抽象类,因为接口可以继承接口,所以在分类向下划分的时候通常都使用接口,比如动物可以分为哺乳动物,卵生动物。而哺乳动物又分为大型动物,小型动物,再细分其具体动物。如果用抽象类会受到单继承限制。无法一步步细分,所以在能够同时使用接口和抽象类的前提下尽量使用接口

1.接口需要有子类继承(实现)接口

2.接口中方法有 抽象方法 后来的 default的普通方法 和 static方法

3.接口相比于抽象类,子类可以继承(实现)多个接口

案例代码:创建动物接口

package Example92;
//利用接口的特性将animal分成两个部分用以突出接口的特点
interface animalPiece1 {
    public abstract void eat();
    public default void test() {
        System.out.println("default方法");
    }
    public static Dog dogReturn() {
        return new Dog();
    }//static方法
}
interface animalPiece2 {
    public abstract void shout();
}
class Dog implements animalPiece1, animalPiece2 {
    @Override
    public void eat() {
        System.out.println("吃吃吃吃吃");
    }
    @Override
    public void shout() {
        System.out.println("叫叫叫叫叫");
    }
}
public class javaDemo {
    public static void main(String[] args) {
        animalPiece1 animal = new Dog();//通过向上转型
        animalPiece1 animal1 = animalPiece1.dogReturn();
        animal.test();
        animal.eat();
    }
}

image.gifimage.gif

 *面试题: 接口和抽象类有什么区别?

(1)接口

接口使用interface修饰;

接口不能实例化;

类可以实现多个接口;

①java8之前,接口中的方法都是抽象方法,省略了public abstract。②java8之后;接口中可以定义静态方法,静态方法必须有方法体,普通方法没有方法体,需要被实现;

(2)抽象类

抽象类使用abstract修饰;

抽象类不能被实例化;

抽象类只能单继承;

抽象类中可以包含抽象方法和非抽象方法,非抽象方法需要有方法体;

如果一个类继承了抽象类,①如果实现了所有的抽象方法,子类可以不是抽象类;②如果没有实现所有的抽象方法,子类仍然是抽象类。


三.设计模式

抽象类的模板模式 接口的工厂设计模式和代理模式

抽象类:模板模式

抽象类的模板模式(Template Pattern): 模板模式是一种行为设计模式,它通过定义一个抽象类作为模板,其中包含一个算法的骨架,将一些方法的实现推迟到具体子类中。这使得子类可以在不改变算法结构的情况下重写特定的步骤。抽象类充当模板的角色,定义了整个算法的流程和顺序,而具体子类提供特定步骤的实现。

案例代码: 煮茶和泡咖啡就是一个比较典型的例子,完成喝咖啡或者茶的动作就只有加入茶叶和咖啡不同其他的行为就都一样,一样的喝东西行为就是一个模板。

package Example3_1;
abstract class Action{
    public final void drink(){
        boilWater();
        addYoulike();
        spour();
        drinking();
    }
//    共同步骤
    public void boilWater(){
        System.out.println("正在煮水");
    }
//    子类需要独自完成的步骤
    protected abstract void addYoulike();
//    共同步骤
    public void spour(){
        System.out.println("搅拌");
    }
//    共同步骤
    public void drinking(){
        System.out.println("可以喝了,一口气喝完");
    }
}
class Coffee extends Action{
    @Override
    protected void addYoulike() {
        System.out.println("加入咖啡粉");
    }
}
class Tea extends Action{
    @Override
    protected void addYoulike() {
        System.out.println("加入茶叶");
    }
}
public class javaDemo {
    public static void main(String[] args) {
        Action tea = new Tea();
        tea.drink();
        System.out.println("----------------------");
        Action coffee = new Coffee();
        coffee.drink();
    }
}

image.gif

image.gif

 接口:工厂设计模式 代理设计模式

1.工厂设计模式

接口的工厂设计模式(Factory Design Pattern): 工厂设计模式是一种创建型设计模式,用于创建对象的过程被封装在一个共同的接口中。它通过定义一个工厂接口和多个具体的工厂类来实现对象的创建,由客户端通过工厂接口来请求对象的创建,而不需要关心具体的实现类。接口定义了创建对象的标准和方法,而具体的工厂类负责实现对象的创建逻辑。

案例:一个比较典型的汽车工厂CarFactory 里面有SuvCar,Bus,我可以自己通过输入字符串比如Bus就能自动创建相应的对象

package Example4;
//定义汽车接口内部有汽车信息输出
interface Car{
    public void carInfomation();
}
//定义Suv汽车与其相关信息
class SuvCar implements  Car{
    private int price = 1000000;
    @Override
    public void carInfomation() {
        System.out.println("Suv车型的造价为"+this.price);
    }
}
//定义Bus汽车与其相关信息
class Bus implements Car{
    private int price = 5000000;
    @Override
    public void carInfomation() {
        System.out.println("Bus车型的造价为"+this.price);
    }
}
//定义汽车工厂,用以生产对应汽车实例
class CarFactory{
    public static Object makeCar(String str){
//        实现动态创建对象并且忽略传入值的大小写
        if (str.equalsIgnoreCase("SuvCar")){
            return new SuvCar();
        }
        if (str.equalsIgnoreCase("Bus")){
            return new Bus();
        }
        return null;
    }
}
public class javaDemo {
    public static void main(String[] args) {
        Bus bus = (Bus) CarFactory.makeCar("bus");
        bus.carInfomation();
        SuvCar suvCar =(SuvCar) CarFactory.makeCar("suvcar");
        suvCar.carInfomation();
    }
}

image.gif

image.gif编辑

       面试题:使用工厂模式最主要的好处是什么?在哪里使用?

1、工厂模式好处

    • 良好的封装性、代码结构清晰;
    • 扩展性好,如果想增加一个产品,只需扩展一个工厂类即可;
    • 典型的解耦框架;

    2、在哪里使用?

      • 需要生成对象的地方;
      • 不同数据库的访问;

      2.代理模式:

      接口的代理模式(Proxy Pattern): 代理模式是一种结构型设计模式,它提供了一个代理类来控制对另一个对象的访问。代理类和原始对象实现了同样的接口,客户端通过代理类来访问原始对象,并且可以在代理类中添加额外的功能,如权限验证、缓存等。接口定义了客户端与代理类和原始对象之间的交互方式,而代理类充当了对原始对象的访问控制和附加功能的提供者。

      案例:代理类内部会将所有对象实例化,所以主类只要实例化代理类就等于把所有的类对象都实例化过一遍,只需要调用自己想要的代理方法就行。核心就在于主类是通过代理类间接访问对象

      package Example5;
      interface Plant{
          public void plant();
      }
      //花朵
      class Flower implements Plant{
          public void plantTime(){
              System.out.printf("在春季适合");
          }
          @Override
          public void plant() {
              System.out.println("种植花朵");
          }
      }
      //小麦
      class Wheat implements Plant{
           Wheat(){}
          public void plantTime(){
              System.out.printf("在冬季适合");
          }
          @Override
          public void plant() {
              System.out.printf("种植小麦");
          }
      }
      //设置代理类
      class plantProxy{
      //    代理类内部创建对象
          private Flower flower = new Flower();
          private Wheat wheat = new Wheat();
          public void getFlowerInfo(){
              this.flower.plantTime();
              this.flower.plant();
          }
          public void getWheat(){
              this.wheat.plantTime();
              this.wheat.plant();
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
              plantProxy proxy = new plantProxy();
              proxy.getFlowerInfo();
              proxy.getWheat();
          }
      }

      image.gif

      image.gif编辑

      面试题 请列举出在 JDK 中几个常用的设计模式?

      1、单例模式

      作用:保证类只有一个实例。

      JDK中体现:Runtime类。

      2、静态工厂模式

      作用:代替构造函数创建对象,方法名比构造函数清晰。

      JDK中体现:Integer.valueOf、Class.forName

      3、抽象工厂

      作用:创建某一种类的对象。

      JDK中体现:Java.sql包。

      4、原型模式

      clone();

      原型模式的本质是拷贝原型来创建新的对象,拷贝是比new更快的创建对象的方法,当需要大批量创建新对象而且都是同一个类的对象的时候考虑使用原型模式。

      一般的克隆只是浅拷贝(对象的hash值不一样,但是对象里面的成员变量的hash值是一样的)。

      有些场景需要深拷贝,这时我们就要重写clone方法,以ArrayList为例:

      5、适配器模式

      作用:使不兼容的接口相容。

      JDK中体现:InputStream、OutputStream。

      6、装饰器模式

      作用:为类添加新的功能,防止类继承带来的类爆炸。

      JDK中体现:io类、Collections、List。

      7、外观模式

      作用:封装一组交互类,一直对外提供接口。

      JDK中体现:logging包。

      8、享元模式

      作用:共享对象、节省内存。

      JDK中体现:Integer.valueOf、String常量池。

      9、代理模式

      作用:

      (1)透明调用被代理对象,无须知道复杂实现细节;

      (2)增加被代理类的功能;

      JDK中体现:动态代理。

      10、迭代器模式

      作用:将集合的迭代和集合本身分离。

      JDK中体现:Iterator

      11、命令模式

      作用:封装操作,使接口一致。

      JDK中体现:Runable、Callable、ThreadPoolExecutor。

      面试题什么是设计模式?你是否在你的代码里面使用过任何设计模式?

      1、什么是设计模式?

      设计模式是解决软件开发某些特定问题而提出的一些解决方案,也可以理解为解决问题的一些固定思路。

      通过设计模式可以帮助我们增强代码的可复用性、可扩展性、灵活性。

      我们使用设计模式的最终目的是实现代码的高内聚、低耦合。

      2、设计模式的七大原则

         单一职责原则

         接口隔离原则

         依赖倒转原则

         里式替换原则

         开闭原则

         迪米特法则

         合成复用原则

      3、你是否在你的代码里面使用过任何设计模式?

      (1)单例模式

      JDK种的runtime,Spring种的singeton。

      (2)简单工厂模式

      Spring的BeanFactory,根据传入一个唯一标识来获得bean对象。

      (3)原型模式

      clone()

      (4)代理模式

      Spring的AOP中,Spring实现AOP功能的原理就是代理模式,①JDK动态代理。②CGLIB动态代理,使用Advice(通知)对类进行方法级别的切面增强。

      (5)装饰器模式

      为类添加新的功能,防止类爆炸;

      IO流、数据源包装,Spring中用到的装饰器模式表现在Wrapper。


      四.包装类

      1.功能

      1.大家熟悉String是作为一个类,而并非数据类型,所以为了将int double float boolean等等这些基本的数据类型也转为一个类,就是所谓包装,每个数据类型对应的类分别是 int ->Integer类double->Double类 boolean->Boolean类

      2.数据转换

      核心的几个函数

      方法 描述
      Integer.parseInt(String s) 将字符串参数解析为带符号的十进制整数。如果字符串无效或格式不正确,将抛出 NumberFormatException 异常。返回解析后的整数值。
      Double.parseDouble(String s) 将字符串参数解析为一个双精度浮点数。如果字符串无效或格式不正确,将抛出 NumberFormatException 异常。返回解析后的浮点数值。
      Boolean.parseBoolean(String s) 将字符串参数解析为布尔值。如果字符串是忽略大小写的 "true",则返回 true;否则返回 false。
      String.valueOf(Object obj) 返回给定对象的字符串表示。如果对象为 null,则返回字符串 "null"。

      案例代码:

      package Example96;
      public class javaDemo {
          public static void main(String[] args) {
      //        String通过包装类Integer的parseInt函数将str转为int
              String str= "123";
              int number = Integer.parseInt(str);
              System.out.println(number*number);
      //        将number*number通过String的valueOf转为字符串类型
              String str1 =String.valueOf(number*number);
              System.out.println(str1);
      //        将String转为boolean类型
              String str2 = "true";
              boolean flag = Boolean.parseBoolean(str2);
          }
      }

      image.gif

      image.gif编辑

      3.Object类接受所有类型数据

      1.Object类是所有类的父类,那也就意味着Object可以接受所有的数据类型,也就是说如果在不知道方法要接受什么具体类型的数据时候,那么就进行Object定义并接受对应内容,到时候再进行强制向下转型。

       

      image.gif编辑

      问题引出:但是强制向下转型可能会出现ClassCaseException错误,而如果用之前的instanceOf可能会非常麻烦,因为定义的数据可能是字符串但是将其强行向下转型到(Integer)类型则会报错,为此就提出一个新的概念--泛型


      五.泛型

      泛型是为了避免出现ClassCaseException的异常而出现,而该异常大概率是因为强制向下转型而出现的问题,故此泛型的解决办法就是避免出现向下转型

      1.泛型的格式

      类需要进行标记<>

      2.泛型的引用与泛型引用通配符 “?”传递数据的上限和下限

      1.泛型的引用:

      package Example98;
      class test<T> {
          private T test1;
          public void setTest1(T test1) {
              this.test1 = test1;
          }
          public T getTest1() {
              return test1;
          }
          public void Test() {
              System.out.println(test1);
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
              test<String> t = new test<String>();
              t.setTest1("123");
              t.Test();
              fun(t);
          }
          public static void fun(test<?> test) {
              System.out.println(test.getTest1());
      //        无法对test值进行操作
          }
      }

      image.gif

       2.通配符 “?”传递数据的上限和下限以及区别:

      <?extends Number>:

      只能用Number类或者其子类(Integer Double Boolean)即所谓上限,父类受到限制

      <?super String>:

      只能用String类或者其父类Object类即所谓下线,子类受到限制

      3.泛型的作用

      当我们编写代码时,可能会遇到需要处理多种数据类型的情况。泛型就像是一种通用的工具,它可以让我们在不同的地方使用相同的代码来处理不同的数据类型。

      举个例子,假设我们有一个存储整数的容器类。如果没有泛型,我们可能需要为存储整数、字符串、浮点数等不同类型的值分别编写不同的容器类。这样就会导致代码重复,增加维护难度。

      而有了泛型,我们可以编写一个通用的容器类,在需要存储不同类型的值时,只需要指定具体的类型,让泛型去帮助我们处理具体的类型操作。这样,我们就可以使用相同的代码去处理不同的数据类型,比如添加、删除、获取值等操作。

      在使用泛型的时候,并不能直接修改泛型类中定义的属性。但是,我们可以通过提供方法(setter 和 getter)来操作和修改泛型类中的属性。这样,外部代码可以通过调用方法来改变内部属性的值。

      总的来说,泛型的作用就是让我们能够编写通用、可复用的代码,用于处理不同的数据类型。它简化了代码的编写,提高了代码的可读性和可维护性。虽然不能直接修改泛型类中的属性,但我们可以通过方法来操作和修改属性的值。

      目录
      相关文章
      |
      1月前
      |
      机器学习/深度学习 人工智能 NoSQL
      JAVA接入DeepSeek大模型接口开发---阿里云的百炼模型
      随着大模型的越来越盛行,现在很多企业开始接入大模型的接口,今天我从java开发角度来写一个demo的示例,用于接入DeepSeek大模型,国内的大模型有很多的接入渠道,今天主要介绍下阿里云的百炼模型,因为这个模型是免费的,只要注册一个账户,就会免费送百万的token进行学习,今天就从一个简单的可以执行的示例开始进行介绍,希望可以分享给各位正在学习的同学们。
      211 3
      JAVA接入DeepSeek大模型接口开发---阿里云的百炼模型
      |
      8天前
      |
      Java 编译器 API
      Java Lambda 表达式:以 Foo 接口为例深入解析
      本文深入解析了 Java 8 中 Lambda 表达式的用法及其背后的函数式接口原理,以 `Foo` 接口为例,展示了如何通过简洁的 Lambda 表达式替代传统匿名类实现。文章从 Lambda 基本语法、函数式接口定义到实际应用层层递进,并探讨默认方法与静态方法的扩展性,最后总结常见误区与关键点,助你高效优化代码!
      29 0
      |
      8天前
      |
      Java
      java中一个接口A,以及一个实现它的类B,一个A类型的引用对象作为一个方法的参数,这个参数的类型可以是B的类型吗?
      本文探讨了面向对象编程中接口与实现类的关系,以及里氏替换原则(LSP)的应用。通过示例代码展示了如何利用多态性将实现类的对象传递给接口类型的参数,满足LSP的要求。LSP确保子类能无缝替换父类或接口,不改变程序行为。接口定义了行为规范,实现类遵循此规范,从而保证了多态性和代码的可维护性。总结来说,接口与实现类的关系天然符合LSP,体现了多态性的核心思想。
      19 0
      |
      2月前
      |
      缓存 Java 应用服务中间件
      java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
      java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
      378 5
      |
      4月前
      |
      数据采集 JSON Java
      利用Java获取京东SKU接口指南
      本文介绍如何使用Java通过京东API获取商品SKU信息。首先,需注册京东开放平台账号并创建应用以获取AppKey和AppSecret。接着,查阅API文档了解调用方法。明确商品ID后,构建请求参数并通过HTTP客户端发送请求。最后,解析返回的JSON数据提取SKU信息。注意遵守API调用频率限制及数据保护法规。此方法适用于电商平台及其他数据获取场景。
      |
      5月前
      |
      Java
      Java基础(13)抽象类、接口
      本文介绍了Java面向对象编程中的抽象类和接口两个核心概念。抽象类不能被实例化,通常用于定义子类的通用方法和属性;接口则是完全抽象的类,允许声明一组方法但不实现它们。文章通过代码示例详细解析了抽象类和接口的定义及实现,并讨论了它们的区别和使用场景。
      |
      7月前
      |
      Java
      Java——抽象类和接口
      抽象类是一种不能被实例化的类,至少包含一个抽象方法(无实现体的方法),常用于定义一组相关类的共同特征,并强制子类实现特定方法。抽象方法不能被 `static` 或 `final` 修饰,且必须被重写。 接口则是一个完全抽象的类,用于规范类的行为。接口使用 `interface` 关键字定义,不能实例化,并且类与接口之间是实现关系。 内部类是在一个类内定义的类,分为成员内部类、静态内部类、局部内部类和匿名内部类。成员内部类可被修饰符修饰,静态内部类只能访问外部类的静态成员,局部内部类定义在方法内,匿名内部类则隐藏了名字,直接通过 `new` 关键字定义并实现接口或继承类。
      52 5
      Java——抽象类和接口
      |
      6月前
      |
      安全 Java 数据安全/隐私保护
      【一步一步了解Java系列】:探索抽象类与接口的秘密
      【一步一步了解Java系列】:探索抽象类与接口的秘密
      39 3
      |
      6月前
      |
      Java
      Java中抽象类和接口有什么区别?
      本文阐述了Java中抽象类和接口的区别,包括类型扩展、方法/属性访问控制符、方法实现、使用目的等方面的不同,并提供了抽象类和接口的使用示例,以及Java中其他类型的类(普通类、内部类等)的简介。
      938 0
      Java中抽象类和接口有什么区别?
      |
      6月前
      |
      Java 编译器
      【Java】用一个动物王国的例子,讲清楚抽象类和接口
      【Java】用一个动物王国的例子,讲清楚抽象类和接口
      63 0

      热门文章

      最新文章