【泛型】Generic 参数化类型 类型转换
关于泛型的一些重要知识点
- 【? extends E】接收E类型或者E的子类型对象。上限。一般存储对象的时候用。比如 添加元素 addAll。
- 【? super E】接收E类型或者E的父类型对象。下限。一般取出对象的时候用。比如比较器。
- 1、表示多个可变类型之间的相互关系:HashMap<T,S>表示类型T与S的映射,HashMap<T, S extends T>表示T的子类与T的映射关系。
- 2、细化类的能力:ArrayList<T> 可以容纳任何指定类型T的数据,当T代指人,则是人的有序列表,当T代指杯子,则是杯子的有序列表,所有对象个体可以共用相同的操作行为。
- 3、复杂类型被细分成更多类型:List<People>和List<Cup>是两种不同的类型,这意味着List<People> listP = new ArrayList<Cup>()是不可编译的。这种检查基于编译时而非运行时,所以说是不可编译并非不可运行,因为运行时ArrayList不保留Cup信息。另外要注意,即使People继承自Object,List<Object> listO = new ArrayList<People>()也是不可编译的,应理解为两种不同类型。因为listO可以容纳任意类型,而实例化的People列表只能接收People实例,这会破坏数据类型完整性。
泛型的基本概念
public interface java.lang.reflect.ParameterizedType extends Typepublic interface java.lang.reflect.GenericDeclaration
所有已知实现类:Class、Constructor、Method实例分析
public class ArrayList{
    public Object get(int i){......}
    public void add(Object o){......}
    ......
    private Object[] elementData;
} - 没有错误检查,可以向数组列表中添加任何类的对象
- 在取元素的时候,需要进行强制类型转换
/**jdk1.5之前的写法,容易出问题*/
ArrayList arrayList1=new ArrayList();
arrayList1.add(1);
arrayList1.add(1L);
arrayList1.add("asa"); 
int i=(Integer) arrayList1.get(1);//因为不知道取出来的值的类型,类型转换的时候容易出错  /** jdk1.5之后加入泛型*/
ArrayList<String> arrayList2=new ArrayList<String>();  //限定数组列表中的类型
//arrayList2.add(1); //因为限定了类型,所以不能添加整形
//arrayList2.add(1L);//因为限定了类型,所以不能添加整长形
arrayList2.add("asa");//只能添加字符串
String str=arrayList2.get(0);//因为知道取出来的值的类型,所以不需要进行强制类型转换  泛型的使用
泛型类:类名后面
public class HashMap<K,V> {
    public V put(K key, V value) {...}
    public V get(Object key) {...}
    ...
}public class Pair<T> {
	private T value;
	public Pair(T value) {
		this.value = value;
	}
	public T getValue() {
		return value;
	}
	public void setValue(T value) {
		this.value = value;
	}
}public static void main(String[] args) throws ClassNotFoundException {
	Pair<String> pair = new Pair<String>("Hello");//注意,"="号左边和右边都要使用<>指定泛型的实际类型
	String str = pair.getValue();
	pair.setValue("World");
}class Pair<T, S, P, U, E> { }泛型接口
interface Show<T,U>{
    void show(T t,U u);
} public class ShowTest implements Show<String, Date> {
	@Override
	public void show(String t, Date u) {
		System.out.println(t + "  " + u.getTime());
	}
}Show<String, Date> show = new ShowTest();
show.show("包青天", new Date());泛型方法:返回值之前
class Person<S> {
	public <W> void show(W w) {//这里的【W】完全等价于Object
		if (w != null) System.out.println(w.toString());
	}
	public static <Y> void staticShow(Y y) {
		if (y != null) System.out.println(y.toString());
		//静态方法不能访问在类声明上定义的类型变量
		//S s;//错误提示:Cannot make a static reference to the non-static type S
	}
}泛型变量的类型限定
- 无限定的泛型变量等价于Object(白哥添加)
- 不管该限定是类还是接口,统一都使用关键字 extends
- 可以使用 & 符号给出多个限定
- 如果限定既有接口也有类,那么类必须只有一个,并且放在首位置
public static <T extends Comparable> T get(T t1,T t2)  //继承或实现都用extends
public static <T extends Comparable & Serializable> T get(T t1,T t2)  //使用 & 符号给出多个限定
public static <T extends Object & Comparable & Serializable> T get(T t1,T t2)  //继承的类Object必须放在首位通配符?的使用
- 无限定通配符 形式<?>
- 上边界限定通配符 形式< ? extends Number>
- 下边界限定通配符 形式< ? super Number>
public static void main(String[] args) throws Exception {
	List<Integer> listInteger = new ArrayList<Integer>();
	printCollection(listInteger);//报错 The method printCollection(Collection<Object>) in the type Test is not applicable for the arguments (List<Integer>)
}
public static void printCollection(Collection<Object> collection) {
	for (Object obj : collection) {
		System.out.println(obj);
	}
}public static void printCollection(Collection<?> collection) {...}collection.add(new Object());//The method add(capture#1-of ?) in the type Collection<capture#1-of ?> is not applicable for the arguments (Object)List<? extends Number> x = new ArrayList<Integer>();//正确
List<? extends Number> y = new ArrayList<Object>();//错误  Type mismatch: cannot convert from ArrayList<Object> to List<? extends Number>List<? super Number> y = new ArrayList<Object>();//正确
List<? super Number> x = new ArrayList<Integer>();//错误  Type mismatch: cannot convert from ArrayList<Integer> to List<? super Number>类型擦除
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
System.out.println((list1.getClass() == list2.getClass()) + "  " + (list1.getClass() == ArrayList.class));//true  trueList<Integer> list = new ArrayList<Integer>();
list.add(10086);
Method method = list.getClass().getMethod("add", Object.class);
//运行时利用反射机制调用集合的add方法,跳过编译时的泛型检查
method.invoke(list, "虽然集合中对元素限定的泛型是Integer,但是也能通过反射把字符串添加到集合中");
Object object = list.get(1);
System.out.println(object.getClass().getSimpleName() + "  " + (object.getClass() == String.class));//String  true
try {
    System.out.println(((Object) list.get(1)).getClass());//class java.lang.String
    System.out.println(list.get(1).getClass());//如果不指定list.get(1)的类型,则会默认将其强制转换为集合上指定的泛型类型
} catch (Exception e) {
    e.printStackTrace();//java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
}类型擦除后保留的原始类型
class Pair<T> {
    private T value;
    public T getValue() {
        return value;
    }
    public void setValue(T  value) {
        this.value = value;
    }
} class Pair {
    private Object value;
    public Object getValue() {
        return value;
    }
    public void setValue(Object  value) {
        this.value = value;
    }
} public class Pair<T extends Comparable& Serializable> { ... } public class Pair<T extends Serializable & Comparable> - 在不指定泛型的时候,泛型变量的类型为 该方法中的几种类型的同一个父类的最小级,直到Object。
- 在指定泛型的时候,该方法中的几种类型必须是该泛型实例类型或者其子类。
public class Test {
	public static void main(String[] args) {
		/**不指定泛型的时候,泛型变量的类型为 该方法中的几种类型的同一个父类的最小级,直到Object*/
		int i = Test.add(1, 2); //这两个参数都是Integer,所以T为Integer类型
		Number f = Test.add(1, 1.2);//这两个参数一个是Integer,一个是Float,所以取同一父类的最小级,为Number
		Object o = Test.add(1, "asd");//这两个参数一个是Integer,一个是Float,所以取同一父类的最小级,为Object
		/**指定泛型的时候,该方法中的几种类型必须是该泛型实例类型或者其子类*/
		int a = Test.<Integer> add(1, 2);//指定了Integer,所以只能为Integer类型或者其子类
		//int b = Test.<Integer> add(1, 2.2);//编译错误,指定了Integer,不能为Float
		Number c = Test.<Number> add(1, 2.2); //指定为Number,所以可以为Integer和Float
	}
	public static <T> T add(T x, T y) {
		return y;
	}
}附加:GenericDeclaration 接口
public interface java.lang.reflect.GenericDeclaration- TypeVariable<?>[] getTypeParameters() 返回声明顺序的 TypeVariable 对象的数组,这些对象表示由此 GenericDeclaration 对象表示的一般声明声明的类型变量。
- 返回:表示由此一般声明声明的类型变量的 TypeVariable 对象的数组
- 如果底层的一般声明未声明任何类型变量,则返回一个 0 长度的数组。
public static <T extends Person, U> void main(String[] args) throws Exception {
    Method method = Test.class.getMethod("main", String[].class);
    TypeVariable<?>[] tvs = method.getTypeParameters();//返回声明顺序的 TypeVariable 对象的数组
    System.out.println("声明的类型变量有:" + Arrays.toString(tvs));//[T, U]
    for (int i = 0; i < tvs.length; i++) {
        GenericDeclaration gd = tvs[i].getGenericDeclaration();
        System.out.println("【GenericDeclaration】" + gd);//public static void com.bqt.Test.main(java.lang.String[]) throws java.lang.Exception
        System.out.println(gd.getTypeParameters()[i] == tvs[i]);//true。    GenericDeclaration和TypeVariable两者相互持有对方的引用
        System.out.println(tvs[i] + "  " + tvs[i].getName() + "  " + Arrays.toString(tvs[i].getBounds()));//T  T  [class com.bqt.Person] 和 U  U  [class java.lang.Object]
    }
}【泛型】Generic 参数化类型 类型转换的更多相关文章
- 泛型 Generic 类型擦除引起的问题及解决方法
		参考:http://blog.csdn.net/lonelyroamer/article/details/7868820#comments 因为种种原因,Java不能实现真正的泛型,只能使用类型擦除来 ... 
- Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口
		Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ... 
- C#泛型(Generic)
		一.什么是泛型 泛型(Generic)是C#语言2.0.通用语言运行时(CLR)2.0..NET Framework2.0推出来的新特性. 泛型为.NET框架引入类型参数(Type Parameter ... 
- Java - 泛型 ( Generic )
		Java - 泛型 ( Generic ) > 泛型的特点 > 解决元素存储的安全性问题 > 解决获取数据元素时,需要类型强转的问题 ... 
- 谈一谈从 Delphi 2009 之后就支援的重要功能 – 泛型 (Generic)
		前言 在C++的语言基础当中,除了物件导向.事件驱动的概念之外,模版设计(Template)也是非常重要的一环.然而,C++的开发人员能够善用模版设计的并不多.模版设计这个好物,一般还有一个名称,就是 ... 
- JAVA中的泛型(Generic)
		Java泛型(Generic)简介 泛型是jdk1.5版本以后推出来的,表示类型参数化,让java能更具有动态性一些,让类型能变成参数传递. 要我自己感觉的话,泛型本身没啥用,跟反射在一起用,就体现出 ... 
- Dephi泛型generic的应用
		Dephi泛型generic的应用 泛型在C++, C#中已有广泛应用,Delphi自2009版本也引入泛型,典型的应用如TList,TDictionary.如果你熟悉C#,其用法十分类似. 比如 ... 
- Java基础之Comparable接口, Collections类,Iterator接口,泛型(Generic)
		一.Comparable接口, Collections类 List的常用算法: sort(List); 排序,如果需要对自定义的类进行排序, 那就必须要让其实现Comparable接口, 实现比较两个 ... 
- Java自学-集合框架 泛型Generic
		ArrayList上使用泛型 步骤 1 : 泛型 Generic 不指定泛型的容器,可以存放任何类型的元素 指定了泛型的容器,只能存放指定类型的元素以及其子类 package property; pu ... 
随机推荐
- kafka和springboot整合应用
			加载依赖 <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>s ... 
- hdu  2275  Kiki & Little Kiki 1  水题
			题目:http://acm.hdu.edu.cn/showproblem.php?pid=2275 这个题比较简单,所以就没有测试样例提供给大家,基本把题目的样例过了就可以了 题目大意 给你一串操作, ... 
- 哪种写法更好?<script></script> vs/or <script type=”text/javasript”></script>
			一直很奇怪 哪种写法更好<script type=“text/javascript”>…</script> or <script>…</script>? ... 
- cloudstack模板
			玩cloudstack的人都应该玩过模板这个功能,这里还是比较有意思的,我们底层连接vcenter 创建vm采用模板 实际这里的磁盘方案,并不是给系统重新分配的磁盘大小而是又新挂上了一块磁盘,新磁盘的 ... 
- cbv
- input用类写的方法
- php最简单最基础入门笔记
			偶然翻到之前刚学php时记录的笔记,特此分享给大家,希望对初学者有所帮助. php网页命名不支持中文 isset($abc) 判断变量是否被定义 empty($abc) 判断变量是否为空 u ... 
- [CF1053C]Putting Boxes Together(线段树)
			http://codeforces.com/blog/entry/62013 两个结论: 1.一定有一个箱子不用动. 2.不动的箱子一定是加权前缀和为S/2的那个. 1显然,2由1易得. 于是问题变为 ... 
- BZOJ.3489.A simple rmq problem(主席树 Heap)
			题目链接 当时没用markdown写,可能看起来比较难受...可以复制到别的地方看比如DevC++. \(Description\) 给定一个长为n的序列,多次询问[l,r]中最大的只出现一次的数.强 ... 
- loj6089 小 Y 的背包计数问题
			link 吐槽: 好吧开学了果然忙得要死……不过为了证明我的blog还没有凉,还是跑来更一波水题 题意: 有n种物品,第i种体积为i,问装满一个大小为n的背包有多少种方案? $n\leq 10^5.$ ... 
