-----------android培训、java培训、java学习型技术博客、期待与您交流!-----------
泛型
一、1,概述:JDK1.5版本后出现的新特性,用于解决安全问题,是一个安全机制
扩展:(JDK升级目的:高效,简化书写,安全)
在JDK1.5版本以前的集合,没有使用泛型,只要是对象,不管什么类型的对象,都可以存储进同一个集合中,JDK1.5版本出现了泛型,这样集合就可以限定某一类型的元素,更安全,并且从集合中获取对象时候,编译器也可以知道这个对象的类型。
好处1:将运行时期出现的问题如:ClassCastException,转移到了编译时期,方便程序员解决问题;
2:不需要再对其进行强制转换,更方便了
2,格式:
通过<E>来定义要操作的引用数据类型,其中E称为类型变量或类型参数
如:ArrayList<String> a1=new ArrayList<String>()
a1.add(“你好”);
a1.add(“abc”);
Sting s=a1.get(0);
3,术语
整个ArrayList<E>称为泛型类型
ArrayList<E>中的E称为类型变量或者类型参数
整个ArrayList<Interger>称为参数化的类型
ArrayList<Interger>中的Interger称为类型参数的实际参数ArrayList称为原始类型
<>发音:typeof
4,参数化类型不考虑类型参数的继承关系(或多态):
举例:
Vector<String> v = new Vector<Object>();//错误,不写Object没错
Vector<Object> v = new Vector<String>();//也错,不要理解说继承父类,或多态
5,在使用Java提供的对象时,什么时候写泛型呢?
在集合框架中很常见,只要见到<>就要定义泛型.
<>就是用来接受类型的
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可
6,泛型与反射
泛型是提供给Javac编译器使用的,可以限定集合中的元素类型,编译完后会去掉”类型”信息,使得程序运行效率不受影响,对应参数化的泛型类型,getClas()返回值和原来类型完全一样.由于编译生成的字节码会去掉泛型的类型信息,所以只要跳过编译器,就可以往某个泛型集合中加入其他类型元素,例如,通过反射得到集合,再调用其add()方法
7,泛型限定:<? extends父类>
<? super父类>
a,限定通配符的上边界:
<? extends Person>:表示可以接受Person类型和其子类如Student
正确:Vector<? extends Number> x = new Vector<Interger>(),因为Number是Interger的父类
错误: Vector<? extends Interger > x = new Vector< Number >()因为Number才是Interger的父类
加强扩展:定义泛型时可以使用&来指定多个边界
在泛型中还可同时使用多个类型参数,在定义它们时候用逗号隔开
b,限定通配符的下边界:
<? super Student >:表示可以接受Student类型和其父类如Person
正确:Vector<? super Interger > x = new Vector< Number >();
错误: Vector<? extends Interger > x = new Vector< Byte >();因为Interger和Byte是同级关系
注意:限定通配符总是包括自己
8,扩展:通过泛型比较器限定
class Comp implements Comparator<Person> {}//定义一个(泛型:父类)的比较器,共子类调用
9,编译器不允许创建类型变量的数组.即在创建数组实例时,数组的元素不能使用参数化的类型,例如下面:
Vector<Integer> vectorList[] = new Vector<Integer>[10];
10,泛型异常
对类型变量表示异常,即泛型异常
//定义一个泛型异常
举例:
//定义一个泛型异常
private static <T extends Exception> void method() throws T {
try {
} catch (Exception e) {
throw(T)e;
}
}
二、泛型实例及方法
1,泛型实例:
package com.heima.biji.genericity;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public abstract class genericity_jiaqiang {
public static void main(String[] args) {
//定义一个双列的集合HashMap
HashMap<String,Integer> maps = new HashMap<String,Integer>();
maps.put("张三", 22);
maps.put("李四", 20);
maps.put("王五", 22);
Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
//forEach迭代Map.Entry集合
for (Map.Entry<String, Integer> entry : entrySet) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
swap(new String[]{"abc","def","ooo"},1,2);//将1和2位置上元素互换
//swap(new int[]{1,2,3,4,5},0,4);//报错,因为编译器不会对new in[3]中的int自动拆箱和装箱,因为new int[3]已经是对象了
Object obj = "aaaa";
String x = conver(obj);
}
//定义一互换方法
private static <T> void swap(T[] a, int i, int j) {
T tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
代码分析:
只有引用类型才能做为泛型方法的实际参数,对应add方法,使用基本类型的数据进行测试没有问题,这是因为自动装箱和拆箱.
Swap(new int[3],语句会报错,因为编译器不会对new in[3]中的int自动拆箱和装箱,因为new int[3]已经是对象了
2,泛型类
如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候要采用泛型类型的方式进行定义,也就是类级别的泛型-----泛型类.
举例:
package com.heima.biji.genericity;
class Worker {
}
class Student {
}
//早期泛型方法
/*
class Tool {
private Object obj;
public void setObject(Object obj) {
this.obj = obj;
}
public Object getObject() {
return obj;
}
}
*/
/**
* 泛型类
* 什么时候定义泛型类?
* 当类中要操作的引用数据类型不确定的时候
* 早期定义Object来完成扩展
* 现在定义泛型类来完成扩展
* 总结:泛型类定义的泛型,在整个类中有效
* 如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就固定了
*/
class Utils<UU> {
private UU u;
public void setObject(UU u) {
this.u = u;
}
public UU getObject() {
return u;
}
}
public class Demo_genericityclass {
public static void main(String[] args) {
/*Tool t = new Tool();
t.setObject(new Worker());
Worker w = (Worker)t.getObject();
*/
Utils<Worker> u = new Utils<Worker>();
u.setObject(new Worker());
Worker w =u.getObject();
}
}
3,泛型方法
将泛型定义在方法上,这样传入什么类型数据就操作什么类型
为了让不同方法可以操作不同类型,而且类型还不确定,就可以将泛型定义在方法上
举例:
package com.heima.biji.genericity;
class Demo_Method {
//泛型方法,将泛型定义在方法上
public <T> void show(T t) {
System.out.println("show:"+t);
}
public <T> void print(T t) {
System.out.println("print:"+t);
}
}
public class Demo_genericity_method {
/**
* 泛型方法:将泛型定义在方法上,这样传入什么类型数据就操作什么类型
* 为了让不同方法可以操作不同类型,而且类型还不确定,就可以将泛型定义在方法上
* @param args
*/
public static void main(String[] args) {
Demo_Method dm = new Demo_Method();
dm.show("hahaha");
dm.show(new Integer(4));
dm.print("hehe");
}
}
4、泛型接口
定义在接口上
举例:
package com.heima.biji.genericity;
//泛型定义在接口上
interface Inter<T> {
void show(T t);
}
class InterImpl<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println("show:"+t);
}
}
public class Demo_genericity_Interface {
public static void main(String[] args) {
InterImpl<Integer> i = new InterImpl<Integer>();
i.show(4);
}
}
5,通配符举例
package com.heima.biji.genericity;
import java.util.*;
import java.util.ArrayList;
import java.util.Iterator;
public class tongpeifu {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("abc");
al.add("abcd");
al.add("abcde");
ArrayList<Integer> al1 = new ArrayList<Integer>();
al1.add(1);
al1.add(2);
al1.add(3);
printColl(al);
printColl(al1);
}
//使用通配符?,可以接受任何类型元素
public static void printColl(ArrayList<?> al) {//ArrayList<String> al=new ArrayList<String>
Iterator<?> it = al.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
结果:
abc
abcd
abcde
1
2
3
6,泛型推断
编译器判断泛型方法的实际类型参数的过程称为类型推断,类型推断是相对于直觉推断的,其实现方法是一种非常复杂的过程。
根据调用泛型方法时实际传递的参数类型或返回值的类型来推断。
a:当某个类型变量只在整个参数列表中的所有参数和返回值中一处被应用了,那么根据调用方法时该处的实际应用类型来确定,
b:当某个类型变量在整个参数列表中的所有参数和返回值中多处被应用了,如果调用方法时这多处的实际应用类型都对应同一种类型来确定
c:当某个类型变量在整个参数列表中的所有参数和返回值中多处被应用了,如果调用方法时这多处的实际应用类型都对应不同的类型,并且没有使用返回值,这时候取多个参数的最大交集类型
d:当某个类型的变量在整个参数列表中的所有参数和返回值中多处应用到,如果调用方法时这多处实际应用类型对应到了不同的类型,并且使用返回值,这时有限考虑返回值的类型
e:参数类型的类型推断具有传递性
-----------android培训、java培训、java学习型技术博客、期待与您交流!-----------
分享到:
相关推荐
day01_Object类、常用API day02_Collection、泛型 day03_List、Set、数据结构、Collections day04_Map,斗地主案例 day05_异常,线程 day06_线程、同步 day07_等待与唤醒案例、线程池、Lambda...Java基础小节练习题答案
收集的java李兴华老师的课件笔记。感觉还不错,适合回顾和新手补习。
java零基础自学 之 JAVA泛型 java零基础自学 之 JAVA泛型
所谓泛型,就是变量类型的参数化。泛型是JDK1.5中一个最重要的特征。通过引入泛型,我们将获得编译时类型的安全和运行时更小的抛出ClassCastException的可能。在JDK1.5中,你可以声明一个集合将接收/返回的对象的...
Java Generics and Collections 英文版,详细描述java 泛型技术
java,学习java泛型,java培训之泛型.pptxjava培训之泛型.pptxjava培训之泛型.pptxjava培训之泛型.pptx
关于java基础的泛型的练习
详细的介绍了集合框架的用法,及其语法规则,剖析了使用的使用注意事项,帮助更牢靠的掌握集合框架的知识及泛型内容。谢谢
Java泛型编程指南.pdf 此文章译自SUN的泛型编程指南
Java 实现泛型List的源码,基本实现了List接口的全部所有方法。欢迎大家发表自己的观点和建议。
基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码....
这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...
java 泛型方法使用示例 java 泛型方法使用示例 java 泛型方法使用示例
java 泛型接口示例 java 泛型接口示例 java 泛型接口示例
java泛型技术之发展,学习JAVA 泛型的不错东东
NULL 博文链接:https://840198532-qq-com.iteye.com/blog/1490705
Java.SE 自定义泛型与泛型的常见陷阱Java.SE 自定义泛型与泛型的常见陷阱
Java中的泛型结构请大家指教并指导有不足的地方给予赐教。
Java泛型学习笔记.pdf
详细的介绍了Java是伪泛型的原因,介绍了类型擦除的内容等。