资讯专栏INFORMATION COLUMN

理解Java中的泛型(一)

YFan / 608人阅读

摘要:参数化的类型其中是参数化的类型。类型参数的实例或实际类型参数其中是类型参数的实例或实际类型参数。它们并没有重载,而且泛型中也不存在重载这一说法。除此之外,我们应该尽量地多用泛型方法,而减少对整个类的泛化,因为泛型方法更容易把事情说明白。

泛型是适用于许多许多的类型 ---《JAVA编程思想》

在Java的面向对象编程过程中, 或许你知道运用继承、接口等一系列面向对象的动作来实现代码复用,解耦等目的。 但是你知道的,原始类的继承是单继承,而接口更是把类型协议写死了。我们的代码能否不要这么死板(当然你可以认为那是完美的), 我们的代码能否适用于更多的不具体的类型?代码更加通用?甚至这个类型你自己都不知道?,没错,在JDK1.5中,JAVA引入了一个新的代码泛化机制---泛型。

你必须事先知道的一些术语

原始类型

List users=new ArrayList();
其中List是原始类型。

参数化的类型

List users=new ArrayList<>();
其中List是参数化的类型。 即把原始类型参数化了。

泛型类型

List users=new ArrayList<>();  
其中List是泛型类型。 

类型变量或类型参数

List users=new ArrayList<>();
其中是类型变量或类型参数。 即一个指向某种类型的变量。 大家知道函数形成参,这里可以看做是"类型形参”。

类型参数的实例或实际类型参数

List users=new ArrayList<>();
其中是类型参数的实例或实际类型参数。  大家知道函数实参,这里可以看做是"类型实参”。

泛型也可以如此简单

在JDK1.5版本以前,我们使用List集合get数据是需要转型的,如下

List users=new ArrayList<>();

users.add("armstrong");

String user = (String) users.get(0);

上面代码中,List集合是可以传入任何Object及它的子类的。我们传入一个String类型的数据,取出来默认是Object,所以你需要转型。使用原始类型的弊端:在程序运行起来的时候,可能会出现转型失败的异常。那么补救方法呢?

Jdk1.5里面是这样定义List:

public interface List extends Collection {    
         
  int size();
       
  boolean isEmpty();
         
   T[] toArray(T[] a);
        
  boolean add(E e);

        ...
 }

你可以看到List类这个原始类型,定义成了接口List泛型类型。类、接口的泛型定义方式是一样的,那么我们可以这样编写之前那段代码:

List  usersGenertor=new ArrayList<>();

usersGenertor.add("armstrong");

String userS =   usersGenertor.get(0);

而且,此时List这个泛型类型集合里面只能添加String类型的对象,其他任何类型的不能添加。这样就保证了我们在编写代码的时候(甚至是编译期间)就能发现代码可能会暴漏隐患的地方。下面代码不能编译:

 List  usersGenertor=new ArrayList<>();
 
 usersGenertor.add(new Object());// error,此处不能添加Object类型
 
 usersGenertor.add(123);// error,此处不能添加Integer类型
 
 String userS =   usersGenertor.get(0);

为了更好的解释泛型的概念。打个比方,我们知道达尔文的《进化论》中说人和猴子的祖先都是猿。但是人只能生人 猴子只能生猴子,虽然有共同的祖先,但是人类不等于猴类 我们也不能说人是猿。人不等于猿~ 那么List后面跟着一个类型变量T,就是指List只能持有指定类型的元素,如果T如果被String替代,那么List就只能持有String, 而List("猿“)和List ("人类")和List ("猴")虽然他们都是从List泛化而来。但是他们不相等,不同的"物种"。

List o=new ArrayList();`//error 不能成立 

有同学会说,这个例子太简单了,能不能来一些有难度的。 其实,我举这个例子的初衷是让大家知道---JDK开发人员引入泛型直到现在最大的好处就是为了解决容器转型的麻烦,而且平时工作中我们用泛型最多的场景是和容器打交道。

非常好用的泛型方法

在定义List的接口源码中我们可以看到如下方法:

 T[] toArray(T[] a);

这个方法的作用是把List中的所有元素转存到另一个指定类型的数组中。List原本装什么类型的元素,那么数组也装同样类型的元素,并且这里传入的类型和返回值类型一致都是类型变量T[]。

那么泛型方法是如何定义的呢? 在上面代码中,我们在返回值的前面类型参数标签来声明定义一个泛型方法,其中T[]依次表示返回值的泛型类型和传入的泛型类型参数。那么如何使用呢?看下面代码:

List  usersGenertor=new ArrayList<>();
usersGenertor.add("zeng");
usersGenertor.add("armstrong");
String[] strings = usersGenertor.toArray(new String[10]);
for (String string : strings) {
    System.out.println("string:_"+string);
}

List  usersGenertor2=new ArrayList<>();
usersGenertor2.add(1);
usersGenertor2.add(2);
Integer[] ints = usersGenertor2.toArray(new Integer[3] );
for (Integer inta : ints) {
    System.out.println("Integer:_"+inta);
}

output:
string:_zeng
string:_armstrong
string:_null
string:_null
string:_null
string:_null
string:_null
string:_null
string:_null
string:_null
Integer:_1
Integer:_2
Integer:_null

上面的代码中toArray方法分别传入了String和Integer两种不同的引用类型。它们并没有重载,而且泛型中也不存在重载这一说法。暂时我们可以简单的想象成String,Integer在编译期间把T这个类型参数变量替换掉了。

除此之外,我们应该尽量地多用泛型方法,而减少对整个类的泛化,因为泛型方法更容易把事情说明白。

参考资料:

《Java编程思想第四版》

《Effective Java》

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

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

相关文章

  • 聊聊Java泛型及实现

    摘要:静态变量是被泛型类的所有实例所共享的。所以引用能完成泛型类型的检查。对于这个类型系统,有如下的一些规则相同类型参数的泛型类的关系取决于泛型类自身的继承体系结构。事实上,泛型类扩展都不合法。 前言 和C++以模板来实现静多态不同,Java基于运行时支持选择了泛型,两者的实现原理大相庭径。C++可以支持基本类型作为模板参数,Java却只能接受类作为泛型参数;Java可以在泛型类的方法中取得...

    lewif 评论0 收藏0
  • 是你眼中的泛型吗?

    摘要:得出的结论是两个方法如果有相同的名称和特征签名,但返回值不同,那他们也是可以合法地共存于一个文件中的。同名方法参数个数顺序类型不同,与返回值类型无关。这是来自中的一个例子。 继《? extends T与? super T》之后,我们再聊聊泛型。 Demo 1 public interface Generator { T next(); } 第一种解决方法,在方法返回类型前加...

    alphahans 评论0 收藏0
  • 初探Java类型擦除

    摘要:可以看到,如果我们给泛型类制定了上限,泛型擦除之后就会被替换成类型的上限。相应的,泛型类中定义的方法的类型也是如此。参考语言类型擦除下界通配符和的区别 本篇博客主要介绍了Java类型擦除的定义,详细的介绍了类型擦除在Java中所出现的场景。 1. 什么是类型擦除 为了让你们快速的对类型擦除有一个印象,首先举一个很简单也很经典的例子。 // 指定泛型为String List list1 ...

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

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

    godiscoder 评论0 收藏0

发表评论

0条评论

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