资讯专栏INFORMATION COLUMN

Java泛型:泛型类、泛型接口和泛型方法

khs1994 / 2303人阅读

摘要:泛型类容器类应该算得上最具重用性的类库之一。也就是说,如果使用泛型方法可以取代将整个类泛化,那么应该有限采用泛型方法。以上,泛型的第一部分的结束。

根据《Java编程思想 (第4版)》中的描述,泛型出现的动机在于:

有许多原因促成了泛型的出现,而最引人注意的一个原因,就是为了创建容器类

泛型类

容器类应该算得上最具重用性的类库之一。先来看一个没有泛型的情况下的容器类如何定义:

public class Container {
    private String key;
    private String value;

    public Container(String k, String v) {
        key = k;
        value = v;
    }
    
    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

Container类保存了一对key-value键值对,但是类型是定死的,也就说如果我想要创建一个键值对是String-Integer类型的,当前这个Container是做不到的,必须再自定义。那么这明显重用性就非常低。

当然,我可以用Object来代替String,并且在Java SE5之前,我们也只能这么做,由于Object是所有类型的基类,所以可以直接转型。但是这样灵活性还是不够,因为还是指定类型了,只不过这次指定的类型层级更高而已,有没有可能不指定类型?有没有可能在运行时才知道具体的类型是什么?

所以,就出现了泛型。

public class Container {
    private K key;
    private V value;

    public Container(K k, V v) {
        key = k;
        value = v;
    }

    public K getKey() {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

    public void setValue(V value) {
        this.value = value;
    }
}

在编译期,是无法知道KV具体是什么类型,只有在运行时才会真正根据类型来构造和分配内存。可以看一下现在Container类对于不同类型的支持情况:

public class Main {

    public static void main(String[] args) {
        Container c1 = new Container("name", "findingsea");
        Container c2 = new Container("age", 24);
        Container c3 = new Container(1.1, 2.2);
        System.out.println(c1.getKey() + " : " + c1.getValue());
        System.out.println(c2.getKey() + " : " + c2.getValue());
        System.out.println(c3.getKey() + " : " + c3.getValue());
    }
}

输出:

name : findingsea
age : 24
1.1 : 2.2
泛型接口

在泛型接口中,生成器是一个很好的理解,看如下的生成器接口定义:

public interface Generator {
    public T next();
}

然后定义一个生成器类来实现这个接口:

public class FruitGenerator implements Generator {

    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}

调用:

public class Main {

    public static void main(String[] args) {
        FruitGenerator generator = new FruitGenerator();
        System.out.println(generator.next());
        System.out.println(generator.next());
        System.out.println(generator.next());
        System.out.println(generator.next());
    }
}

输出:

Banana
Banana
Pear
Banana
泛型方法

一个基本的原则是:无论何时,只要你能做到,你就应该尽量使用泛型方法。也就是说,如果使用泛型方法可以取代将整个类泛化,那么应该有限采用泛型方法。下面来看一个简单的泛型方法的定义:

public class Main {

    public static  void out(T t) {
        System.out.println(t);
    }

    public static void main(String[] args) {
        out("findingsea");
        out(123);
        out(11.11);
        out(true);
    }
}

可以看到方法的参数彻底泛化了,这个过程涉及到编译器的类型推导和自动打包,也就说原来需要我们自己对类型进行的判断和处理,现在编译器帮我们做了。这样在定义方法的时候不必考虑以后到底需要处理哪些类型的参数,大大增加了编程的灵活性。

再看一个泛型方法和可变参数的例子:

public class Main {

    public static  void out(T... args) {
        for (T t : args) {
            System.out.println(t);
        }
    }

    public static void main(String[] args) {
        out("findingsea", 123, 11.11, true);
    }
}

输出和前一段代码相同,可以看到泛型可以和可变参数非常完美的结合。

以上,泛型的第一部分的结束。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64325.html

相关文章

  • JAVA泛型笔记

    摘要:泛型类泛型类和普通类的区别就是类定义时,在类名后加上泛型声明。泛型类的内部成员方法就可以使用声明的参数类型。 泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type),即所操作的数据类型在定义时被指定为一个参数。当我们使用的时候给这个参数指定不同的对象类型,就可以处理不同的对象。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和...

    n7then 评论0 收藏0
  • Java™ 教程(类型推断)

    类型推断 类型推断是Java编译器查看每个方法调用和相应声明的能力,以确定使调用适用的类型参数,推理算法确定参数的类型,如果可用,还确定分配或返回结果的类型,最后,推理算法尝试查找适用于所有参数的最具体类型。 为了说明最后一点,在下面的示例中,推断确定传递给pick方法的第二个参数是Serializable类型: static T pick(T a1, T a2) { return a2; } ...

    JerryC 评论0 收藏0
  • 浅析Java泛型

    摘要:泛型类在类的申明时指定参数,即构成了泛型类。换句话说,泛型类可以看成普通类的工厂。的作用就是指明泛型的具体类型,而类型的变量,可以用来创建泛型类的对象。只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。 什么是泛型? 泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数,...

    godiscoder 评论0 收藏0
  • Java基础-泛型详解

    摘要:泛型方法可以定义在普通类和泛型类中,泛型方法可以被修饰符修饰。泛型类型变量会在编译后被擦除,用第一个限定类型替换没有限定类型的用替换。比如通配符类型代表任何泛型类型的类型变量是和的子类。这个类型参数有一个子类型限定,其自身又是一个泛型类型。 我的博客 转载请注明原创出处。 序 之所以会想来写泛型相关的内容,是因为看到这样的一段代码: showImg(https://segment...

    hearaway 评论0 收藏0
  • java的集合和泛型的知识点归纳1

    摘要:接口也是集合中的一员,但它与接口有所不同,接口与接口主要用于存储元素,而主要用于迭代访问即遍历中的元素,因此对象也被称为迭代器。迭代器的实现原理我们在之前案例已经完成了遍历集合的整个过程。 【Collection、泛型】 主要内容 Collection集合 迭代器 增强for 泛型 教学目标 [ ] 能够说出集合与数组的区别 [ ] 说出Collection集合的常用功能 [ ]...

    daryl 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<