这里不讲泛型的概念和基础知识,就单纯的就我的理解说一下泛型中的<T>

一. <T>

  下面的一段码就可以简单使用了<T>参数,注释就是对<T>的解释。

package xayd.hjj;

import java.util.ArrayList;
import java.util.List; class A{}
class B{}
class C{}
class D extends C{} public class Test<T> extends ArrayList<T>{ public static <T> void main(String[] args) { Test<C> testC = new Test<C>();
// testC = new Test<B>(); //编译错误
//testC = new Test<D>(); //编译错误
//一旦指定了参数为C这个类就不能把这个对象在赋值为其他类型,即便是其父类 testC.add(new C());
//testC.add(new B()); //编译错误,不能在C类的容器中存放无关C的类B的对象
testC.add(new D()); //编译正确,因为父类容器可以放置父类对象,同时也可以放置子类对象 C testC1 = testC.get();
C testC2 = testC.get(); //从父类容器中拿出子类对象,用最初传递的参数类型接收
// D testC3 = testC.get(1); //编译错误
D testC4 = (D) testC.get(); //从父类容器中拿出子类对象,用最初传递的参数类型的子类对象接收,要进行强制类型转换
System.out.println(testC1); //xayd.hjj.C@2a139a55
System.out.println(testC2); //xayd.hjj.D@15db9742
System.out.println(testC4); //xayd.hjj.D@15db9742 } }

  其实继承ArrayList的目的是为了使用add和get方法,以便测试,其实你也可以自己实现类似于add和get的方法。

   ArrayList关于add和get方法的实现如下:

private transient Object[] elementData;
private int size;
public boolean add(E e) {
ensureCapacityInternal(size + );
elementData[size++] = e;
return true;
} public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}

  下面还有一段和上面有点类似的代码。如下:

package xayd.hjj1;

import java.util.ArrayList;
class A{}
class B{} class C{} class D extends C{} public class Test<T> extends ArrayList{ //注意这里不是ArrayList<T>,其实应该相当于ArrayList<Object> public static void main(String[] args) {
Test<C> testC = new Test<C>();
// testC = new Test<D>();//同样编译有错误
testC.add(new C());
testC.add(new A()); //奇怪的是可以通过编译
testC.add(new B()); //这样也可以通过编译
testC.add(new D()); //C objC = testC.get(0); //编译不能通过
Object objC1 = testC.get(0); //编译通过
C objC2 = (C) testC.get(0); //编译通过 //C objC3 = (C) testC.get(1); //这样的结果编译可以通过,但是运行毫无疑问会抛出ClassCastException
A objC4 = (A) testC.get(1); //编译通过,不过这样程序员必须知道容器中第二个对象是A类型.
Object objC5 = (A) testC.get(1); //编译通过
Object objC6 = (Object) testC.get(1); //编译通过 } }

  这段代码和第一段代码的区别就是继承ArrayList时的不同。第一段代码是Test<T> extends ArrayList<T>,这段代码是Test<T> extends ArrayList。从代码运行的结果可以看到这段代码是不安全的,这段代码用testC调用add方法时参数传递没有限制,并不像第一段代码会出现编译错误。而且用get方法拿出时必须进行类型转化,即使你执行了这样的代码 C objC3 = (C) testC.get(1),编译期并不能检查到错误,而是在运行时抛出ClassCastException。

  在这里我对于ArrayList<T>和ArrayList这两种不同写法的解释如下(可能也不太准确,如有错误还请指正):

  Test<T> extends ArrayList<T>: Test<C> testC = new Test<C>(),这样Test和ArrayList的参数类型都为C,因此add方法参数只能传递C和C的子类。从add方法的源码中可以看到是这样添加元素的:elementData[size++] = e,在这里elementData其实是一个Object类型的数组,但是因为你限制了T的参数为类C的类型,所以编译器会限制这Object必须为C类型(或者是它的子类),所以在你加入了其他与类C无关的对象的时候编译是不能通过的。

  Test<T> extends ArrayList: Test<C> testC = new Test<C>(), 这样Test参数类型为C,而ArrayList的参数没有传递,因此默认为Object(public class ArrayList<E>,ArrayList类在源码中是这样的实现形式)。所以只要是Object类型都可以添加,所以才会导致编译期编译器可以无限制的添加任类型却没有任何错误,而运行期拿出时一旦转型错误便抛出异常。

  二.关于上面的代码导致的两种不同结果,是因为ArrayList本身的实现导致的。所以自己实现了一个简单的统一的类重新解释T.

package xayd.hjj2;

import java.util.ArrayList;

class A{}
class B{} class C{} class D extends C{} public class Test<T>{ private T obj; public T getObj() {
return obj;
} public void setObj(T obj) {
this.obj = obj;
} public static <T> void main(String[] args) {
Test<C> testC = new Test<C>();
testC.setObj(new C());
C objC = testC.getObj();
System.out.println(objC); //xayd.hjj2.C@2a139a55 // testC.setObj(new B()); //编译错误 testC.setObj(new D()); //编译成功
C objC1 = testC.getObj();
System.out.println(objC1); //xayd.hjj2.D@15db9742 }
}

  这段代码就比较简单清晰了,Test类和类的成员变量参数类型一致,因此不会有不同的结果。

  

Java泛型之<T>的更多相关文章

  1. JAVA泛型之<? extends T>:(通配符上限)和<? super T>(通配符下限)

    一.通配符上限和通配符下限接受的类型 通配符上限:<? extends T> 通配符下限:<? super T> 以下代码是测试结果,注释为解释说明 package xayd. ...

  2. 浅谈Java泛型之<? extends T>和<? super T>的区别

    关于Java泛型,这里我不想总结它是什么,这个百度一下一大堆解释,各种java的书籍中也有明确的定义,只要稍微看一下就能很快清楚.从泛型的英文名字Generic type也能看出,Generic普通. ...

  3. Java泛型中extends和super的理解(转)

    E – Element (在集合中使用,因为集合中存放的是元素) T – Type(Java 类) K – Key(键) V – Value(值) N – Number(数值类型) ? – 表示不确定 ...

  4. Java泛型中extends和super的理解

    作者:zhang siege链接:https://www.zhihu.com/question/20400700/answer/91106397来源:知乎著作权归作者所有.商业转载请联系作者获得授权, ...

  5. java泛型中extends 和 super的区别

    一般对泛型中extends 和 super 的区别是这样介绍的: 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 < ...

  6. JAVA泛型知识--> <? extends T>和<? super T>

    <? extends T> 和 <? super T> 是Java泛型中的“通配符(Wildcards)” 和 “边界(Bounds)”的概念 <? extends T& ...

  7. Java泛型中extends和super的区别?

    <? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. ...

  8. java泛型<? extends E> 有上限通配符与<? Super E>有上限通配符

    通配符?,?表示占位,表明将来使用的时候在指明类型 <?>无限定的通配符, 是让泛型能够接受未知类型的数据 <? extends E> 有上限通配符,能够接受指定类及其子类类型 ...

  9. Java笔记2 : 泛型的体现,及其上限、下限、通配符

    Java中的泛型是在jdk5.0引入的,语法不难,但是需要注意的细节有很多,这里写一下备忘. 首先是最简单的泛型类,泛型方法,泛型接口: //泛型接口的定义 interface MyInter< ...

  10. Java泛型-通配符的上限和下限问题

    Java的泛型中,通配符可以设置上限和下限. 上限:<? extends T> ?是T和T的子类 下限:<? super T> ?是T和T的父类 怎么看待这个上限和下限呢 首先 ...

随机推荐

  1. Linux 命令整理

    一.文件目录命令 1.建立目录:mkdir 目录名 2.删除空目录:rmdir 目录名 3.无条件删除子目录: rm -rf 目录名 4.改变当前目录:cd 目录名 (进入用户home目录:cd ~; ...

  2. 怎样用HTML5 Canvas制作一个简单的游戏

    原文连接: How To Make A Simple HTML5 Canvas Game 自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML ...

  3. boost 分析命令行参数

    #include <boost/program_options.hpp> #include <iostream> #include <vector> using n ...

  4. 一步一步重写 CodeIgniter 框架 (3) —— 用面向对象重构代码

    前面两篇文章为了重点突出 CodeIgniter 框架的原理,程序的结构很乱,有很多全局变量,在这一课中我们采用面向对象的方法对原先代码进行重构. 到目前为止,程序主要完成的就是 URL 分析,并根据 ...

  5. java调用restful webservice(转)

    一般来说,大家只会用到GET和POST方法来调用. GET方法的话,参数可以写在url里面. 比如说server的interface用的是@RequestParam或者@PathVariable,在客 ...

  6. document.body的一些用法以及js中的常见问题

    document.body的一些用法以及js中的常见问题 网页可见区域宽: document.body.clientWidth; 网页可见区域高: document.body.clientHeight ...

  7. SQL中on条件与where条件的区别(转载)

    数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1. on条件是在生成临时表时使用的条 ...

  8. JSP简单练习-使用JDOM创建xml文件

    注意:在编写代码前,请确保该Web文件夹下的"WEB-INF/lib"下包括jdom.jar包! <%@ page language="java" con ...

  9. 谈论Java原子变量和同步的效率 -- 颠覆你的生活

    我们认为,由于思维定式原子变量总是比同步运行的速度更快,我想是这样也已经,直到实现了ID在第一次测试过程生成器不具有在这样一个迷迷糊糊的东西. 测试代码: import java.util.Array ...

  10. HDU--杭电--3790--最短路径问题

    最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...