汤洪 發表於 2026-3-31 21:18:00

Java 中的 实现、泛型

<p>上次我们聊了 Java&nbsp;面向对象的三大特性,<strong>封装、继承、多态。</strong>今天我们来聊聊 <strong>实现、泛型</strong>。</p>
<p><strong>一、实现(implements)</strong></p>
<p><strong>定义:</strong>"实现"&nbsp;是 Java 中类与接口(Interface) 之间的关系,关键字是 <strong>implements</strong>。接口是一组 <strong>"行为规范"</strong>(只定义方法签名,不包含具体实现),而实现类需要兑现这些规范,即编写接口中所有抽象方法的具体逻辑。</p>
<p><strong>类比:</strong>接口 = 一份 "合同"(比如 Runnable 接口规定 "必须有 run () 方法"),实现类 = 签约方(比如 MyThread 类实现 Runnable,必须写 run () 的具体代码,兑现合同)。</p>
<p><strong>作用:</strong></p>
<ul>
<li><strong>弥补 Java 单继承的不足</strong>:一个类只能继承 1 个父类,但 <strong>可以实现多个接口</strong>(比如class A extends B implements C, D),<strong>实现 "多继承"&nbsp;</strong>的效果;</li>
<li><strong>定义行为标准</strong>:接口封装 "能做什么",实现类负责 "怎么做",解耦行为规范和具体实现;</li>
<li>接口多态的核心基础。</li>
</ul>
<p><strong>示例代码:</strong></p>
<pre class="language-java highlighter-hljs"><code>// 1. 定义接口:封装行为规范(只有方法签名,无实现)
public interface AnimalBehavior {
    // 抽象方法:无方法体
    void eat();
    void move();
   
    // 默认方法(JDK8+):有默认实现,实现类可重写
    default void breathe() {
      System.out.println("动物呼吸空气");
    }
}

// 2. 实现类:必须实现接口的所有抽象方法
public class Dog1 implements AnimalBehavior {
    @Override
    public void eat() {
      System.out.println("狗啃骨头");
    }

    @Override
    public void move() {
      System.out.println("狗跑");
    }

    // 可选:重写接口的默认方法
    @Override
    public void breathe() {
      System.out.println("狗用鼻子呼吸");
    }

    public static void main(String[] args) {
      Dog1 dog1 = new Dog1();
      dog1.eat();    // 输出:狗啃骨头
      dog1.move();   // 输出:狗跑
      dog1.breathe();// 输出:狗用鼻子呼吸
    }
}</code></pre>
<p><strong>二、泛型(Generics)</strong></p>
<p><strong>定义:参数化类型</strong> —— 允许在定义类、接口、方法时使用 "类型参数",编译时指定具体类型,从而实现类型安全和代码复用。</p>
<p><strong>类比:</strong>快递箱(泛型类)可以装任何物品(类型参数),你在使用时指定装 "书籍"(String)或 "电子产品"(Integer),箱子就只接受对应类型,避免装错。</p>
<p><strong>作用:</strong></p>
<ul>
<li><strong>类型安全</strong>:编译时检查类型,避免运行时 ClassCastException(强制类型转换异常);</li>
<li><strong>代码复用</strong>:一套代码支持多种类型,无需为不同类型重复编写;</li>
<li>消除冗余的强制类型转换。</li>
</ul>
<p><strong>泛型类 </strong>示例:</p>
<pre class="language-java highlighter-hljs"><code>// 自定义泛型类:Box&lt;T&gt;,T是类型参数(可以任意命名,常用T/E/K/V)
public class Box&lt;T&gt; {
    private T content;

    // 泛型方法:设置内容
    public void setContent(T content) {
      this.content = content;
    }

    // 泛型方法:获取内容
    public T getContent() {
      return content;
    }

    // 测试泛型类
    public static void main(String[] args) {
      // 1. 指定T为String类型
      Box&lt;String&gt; stringBox = new Box&lt;&gt;();
      stringBox.setContent("Hello 泛型");
      String str = stringBox.getContent(); // 无需强制转换
      System.out.println(str); // 输出:Hello 泛型

      // 2. 指定T为Integer类型
      Box&lt;Integer&gt; integerBox = new Box&lt;&gt;();
      integerBox.setContent(100);
      Integer num = integerBox.getContent();
      System.out.println(num); // 输出:100

      // 3. 类型安全:编译时检查,避免装错类型
      // stringBox.setContent(100); // 编译错误:不能将Integer赋值给String类型的Box
    }
}</code></pre>
<p><strong>泛型方法(独立于类的泛型)</strong>示例:</p>
<pre class="language-java highlighter-hljs"><code>public class GenericMethodDemo {
    // 泛型方法:&lt;T&gt;是方法的类型参数,T[]是参数类型,T是返回类型
    public static &lt;T&gt; T getFirstElement(T[] array) {
      if (array == null || array.length == 0) {
            return null;
      }
      return array;
    }

    public static void main(String[] args) {
      String[] strArray = {"Java", "泛型", "教程"};
      Integer[] intArray = {1, 2, 3, 4};

      // 调用泛型方法,自动推断类型
      String firstStr = getFirstElement(strArray);
      Integer firstInt = getFirstElement(intArray);

      System.out.println(firstStr); // 输出:Java
      System.out.println(firstInt); // 输出:1
    }
}</code></pre>
<p><strong>泛型通配符(&lt;?&gt;、&lt;? extends T&gt;、&lt;? super T&gt;)</strong>示例:</p>
<pre class="language-java highlighter-hljs"><code>// 父类:抽象的"动物"
public class Animal {
    // 父类属性
    protected String name; // protected:子类可直接访问

    // 父类构造方法
    public Animal(String name) {
      this.name = name;
    }

    // 父类方法
    public void eat() {
      System.out.println(name + "在吃食物");
    }

    // 父类方法
    public void sleep() {
      System.out.println(name + "在睡觉");
    }
}

// 子类:Dog2(继承Animal)
public class Dog2 extends Animal {
    // 子类特有属性
    private String breed; // 品种

    // 子类构造方法:必须通过super调用父类构造
    public Dog2(String name, String breed) {
      super(name); // 调用父类的构造方法
      this.breed = breed;
    }

    // 重写(Override)父类方法:扩展/修改父类行为
    @Override
    public void eat() {
      System.out.println(name + "(" + breed + ")在啃骨头");
    }

    // 子类特有方法:扩展父类功能
    public void bark() {
      System.out.println(name + "在汪汪叫");
    }
}

// 子类:Cat(继承Animal)
public class Cat extends Animal {
    public Cat(String name) {
      super(name);
    }

    // 重写eat方法
    @Override
    public void eat() {
      System.out.println(name + "在吃小鱼干");
    }

    // 子类特有方法
    public void meow() {
      System.out.println(name + "在喵喵叫");
    }
}

public class GenericWildcardDemo {
    // 通配符&lt;?&gt;:表示任意类型(只读,不能添加元素)
    public static void printList(List&lt;?&gt; list) {
      for (Object obj : list) {
            System.out.print(obj + " ");
      }
      System.out.println();
    }

    // 上限通配符&lt;? extends Animal&gt;:只能是Animal或其子类
    public static void feedAnimals(List&lt;? extends Animal&gt; animals) {
      for (Animal animal : animals) {
            animal.eat();
      }
    }

    // 下限通配符&lt;? super Dog2&gt;:只能是Dog2或其父类
    public static void addDog(List&lt;? super Dog2&gt; list) {
      list.add(new Dog2("旺财", "金毛")); // 可以添加Dog或其子类
    }

    public static void main(String[] args) {
      List&lt;Dog2&gt; dogs = new ArrayList&lt;&gt;();
      dogs.add(new Dog2("旺财", "金毛"));
      List&lt;Cat&gt; cats = new ArrayList&lt;&gt;();
      cats.add(new Cat("咪宝"));

      // 通配符&lt;?&gt;
      printList(dogs); // 输出:Dog2@6f496d9f - 旺财
      printList(cats); // 输出:Cat@723279cf - 咪宝

      // 上限通配符&lt;? extends Animal&gt;
      feedAnimals(dogs); // 输出:旺财(金毛)在啃骨头
      feedAnimals(cats); // 输出:咪宝在吃小鱼干

      // 下限通配符&lt;? super Dog&gt;
      List&lt;Animal&gt; animals = new ArrayList&lt;&gt;();
      addDog(animals);
      System.out.println(animals.size()); // 输出:1
    }
}</code></pre>
<p><strong>说明:</strong></p>
<ul>
<li><strong>泛型擦除</strong>:Java 的泛型是 "编译时泛型",运行时会擦除类型参数(比如 Box&lt;String&gt; 运行时变成 Box&lt;Object&gt; ),目的是兼容旧代码;</li>
<li><strong>泛型上限</strong>:&lt;? extends T&gt; 表示只能是 T 或其子类(读操作安全);</li>
<li><strong>泛型下限</strong>:&lt;? super T&gt; 表示只能是 T 或其父类(写操作安全);</li>
<li>不能用基本类型作为泛型参数:比如 Box&lt;int&gt; 错误,需用包装类 Box&lt;Integer&gt;。</li>
</ul>
<p><strong>总结:</strong></p>
<ul>
<li><strong>实现</strong>&nbsp; 是类对接口行为规范的 "兑现",核心作用是弥补单继承不足、定义行为标准,是接口多态的基础;</li>
<li><strong>泛型 </strong>是参数化类型,编译时检查类型安全,消除强制转换,核心是类型参数(T/E 等),实现代码复用。</li>
</ul>
<p style="text-align: right"><span style="color: rgba(53, 152, 219, 1)">成功者的目标,不是让别人相信自己是对的,而是弄明白谁是对的。-- 烟沙九洲</span></p><br><br>
来源:https://www.cnblogs.com/yanshajiuzhou/p/19803749
頁: [1]
查看完整版本: Java 中的 实现、泛型