美文网首页
Java随笔-泛型

Java随笔-泛型

作者: 来自蒙塔基的钢蛋儿 | 来源:发表于2019-07-24 12:31 被阅读0次

什么是泛型

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

假定我们有这样一个需求:写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?

答案是可以使用 Java 泛型。

使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整型数组、浮点数数组、字符串数组等进行排序。


泛型的写法

一般我们会有以下两种写法
<T extends InterfaceName <T>><T extends InterfaceName <? super T>>
InterfaceName 是泛型要实现的接口,一般来说我们使用第一种方法声明泛型就可以满足需求.

class Animal implements Comparable<Animal>{
    protected int age;

    public Animal(int age){
        this.age = age;
    }

    public void move() {
        System.out.println("动物可以移动");
    }

    @Override
    public int compareTo(@NonNull Animal animal) {
        return this.age-animal.age;
    }
}

class Main {
    public static <T extends Comparable<T>> void mySort1(List<T> list){
        Collections.sort(list);
    }
    public static <T extends Comparable<? super T>> void mySort2(List<T> list){
        Collections.sort(list);
    }
    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<>();
        animals.add(new Animal(2));
        animals.add(new Animal(1));

        mySort1(animals);
        mySort2(animals);
    }
}

比如上边这段代码,声明两个排序方法,分别使用上述两种方式声明泛型变量.
Animal实现了Comparable接口所以无论使用哪种声明泛型变量的排序方法都可以调用.看不出两种声明方式有什么区别.

下边看这段代码

class Animal implements Comparable<Animal>{
    protected int age;

    public Animal(int age){
        this.age = age;
    }

    public void move() {
        System.out.println("动物可以移动");
    }

    @Override
    public int compareTo(@NonNull Animal animal) {
        return this.age-animal.age;
    }
}
//增加Dog 继承与 Animal
class Dog extends Animal {
    public Dog(int ageInt){
        super(ageInt);
    }
    public void move() {
        System.out.println("狗可以跑和走");
    }

    public void bark() {
        System.out.println("狗可以吠叫");
    }
}

class Main {
    public static <T extends Comparable<T>> void mySort1(List<T> list){
        Collections.sort(list);
    }
    public static <T extends Comparable<? super T>> void mySort2(List<T> list){
        Collections.sort(list);
    }
    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<>();
        animals.add(new Animal(2));
        animals.add(new Animal(1));

        mySort1(animals);
        mySort2(animals);

        List<Dog> dogs = new ArrayList<>();
        dogs.add(new Dog(4));
        dogs.add(new Dog(3));

        mySort1(dogs);
        mySort2(dogs);
    }
}

好,如果执行这段代码java就会稳稳的报错了.

错误: 无法将类 Main中的方法 mySort1应用到给定类型;
需要: List<T>
找到: List<Dog>
原因: 推断类型不符合上限
推断: Dog
上限: Comparable<Dog>
其中, T是类型变量:
T扩展已在方法 <T>mySort1(List<T>)中声明的Comparable<T>

可以看到,虽然Dog继承了Animal,并且它的父类实现了Comparable接口,然而并不可以通过编译,所以我们得到一个答案
<T extends Comparable<T>>这种声明泛型变量的方式,要求当前类本类必须实现接口,无关父类.
<T extends Comparable<? super T>>而这种方式可以通过编译,那么显然它比第一种方式更加灵活,只要它的父类实现了接口,那么它作为泛型入参也是可以满足条件的.


根据上面的小demo可以得出结论:
第一种写法简单但限制必须是当前类实现接口不够灵活,
第二种方法会查找根据继承关系去查找是否有父类实现过接口,有即满足泛型入参要求.更加灵活

大家可以根据具体场景选用泛型变量的声明方式

相关文章

  • Java泛型教程

    Java泛型教程导航 Java 泛型概述 Java泛型环境设置 Java泛型通用类 Java泛型类型参数命名约定 ...

  • 第二十八课:泛型

    泛型出现之前 泛型出现之后 Java深度历险(五)——Java泛型

  • Kotlin 泛型

    说起 kotlin 的泛型,就离不开 java 的泛型,首先来看下 java 的泛型,当然比较熟悉 java 泛型...

  • java泛型中类型擦除的一些思考

    java泛型 java泛型介绍 java泛型的参数只可以代表类,不能代表个别对象。由于java泛型的类型参数之实际...

  • Java泛型

    参考:Java知识点总结(Java泛型) 自定义泛型类 自定义泛型接口 非泛型类中定义泛型方法 继承泛型类 通配符...

  • Java随笔-泛型

    什么是泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机...

  • Java泛型—Java语法糖,只在编译有作用,编译后擦出泛型

    Java泛型—Java语法糖,只在编译有作用,编译后擦出泛型 在代码进入和离开的边界处,会处理泛型 Java泛型作...

  • JAVA 核心笔记 || [xxx] 泛型

    泛型 JAVA 的参数化类型 称为 泛型 泛型类的设计 Learn12.java 运行

  • 简单回顾Java泛型之-入门介绍

    什么时候开始有了Java泛型?什么是Java泛型?为什么要引入Java泛型?什么时候用到了泛型?可不可以给泛型下一...

  • Kotlin 泛型

    Kotlin 支持泛型, 语法和 Java 类似。例如,泛型类: 泛型函数: 类型变异 Java 的泛型中,最难理...

网友评论

      本文标题:Java随笔-泛型

      本文链接:https://www.haomeiwen.com/subject/ftfxrctx.html