泛型:就是声明,声明这个集合要接受什么类型的对象。
jdk1.5出现的安全机制。
泛型出现的原因:
一些方法例如:Add(Object o),添加方法在其向集合添加元素时,其接受的
对象类型定义成了Object,这样可以保证无论你添加什么类型的元素我都可以
添加成功,但是这样就导致之后再取出元素时,无法确定使用什么类型的对象来接收
,会导致取出元素失败,而泛型就是要在放入时就确定了只能放入什么元素,就避免了取出失败。
例如:ArrayList<String> al = new ArrayList<String>();
<>中定义了集合ArrayList中可以存放什么类型的元素。
<>:什么时候用?当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
其实<>就是一个用于接收具体引用数据类型的参数范围。参数范围就是方参数的位置。
例如: void show(int x) 小括号()就是一个参数范围。而x就是参数
ArrayList<E> <>是参数范围,E就是参数
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。
泛型的通配符,以及泛型的限定的表现形式,和用法,以及什么时候用?
? extends E: 存储元素对象的时候用,你定义的是E类型,我们可以存储E类型或者E的子类型的对象。
? super E:从容器中取出元素时使用,容器中有E类型对象,取出时可使用E类型接收,或者E的父类型接收。比如比较器。
泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为
泛型的擦除。
为什么擦除呢?因为为了兼容运行的类加载器。而类加载器是1.4之前的版本,没有升级
在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,
就使用泛型来表示。
例子:
Tool<Student> tool = new Tool<Student>();
tool.setObject(new Worker());这里就会报错,传递错误参数。
自定义泛型:
自定义泛型就是,随便写一个名字代表参数类型,
* 然后Java在接收参数类型时自动自动给你匹配
* 将泛型定义在方法上。
* 不管你调用方法时传递过来什么类型的数据我都可以接收并执行方法
泛型方法:
public void setObject(QQ object)
public <W> void show(W str) 将泛型定义在方法上
这里的意思是:str对象的参数类型是W,而W就是调用方法时传过来的参数类型
调用:Tool<String> tool = new Tool<String>();
//传递过去的是String类型对象
tool.show(new Integer(4));
//传递过去的是Integer类型对象
tool.show("abc");
//传递过去的是String类型对象 * 每调用一次方法就自动匹配一次。
当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型,
* 只能将泛型定义在方法上。
//泛型接口,将泛型定义在接口上。
interface Inter<T>{
public void show(T t);
}
class InterImpl2<Q> implements Inter<Q>{
public void show(Q q){
System.out.println("show :"+q);
}
}
泛型的通配符:? 未知类型。用法就是将<w>,用<?>来替代。
(Conllection<Worker> a1)我只能接收Worker类型的对象。
(Conllection<?> a1)我可以接收所有类型的对象。
但是我既不想只接受一个,也不想全部接收。那就:
(Conllection<? extends Person > a1)定义接收的上限
这句话就是声明我用来接收传递过来的对象的a1只接受继承Person类的对象,
也就是只接受Person的子类。
<? super E>: 接收E类型或者E的父类型对象。 定义接收的下限。
一般取出对象的时候用。比如比较器。
一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。
不会出现类型安全隐患,例如定义成E,就是object类型, 就是可以接收所有object子类
/*Collection(v) values() 建是唯一的,但是值不是唯一的。返回此映射中包含的值的 Collection 视图。
*/ Collection<String> values = map.values();
// Collection<V> values()返回此映射中包含的值的 Collection 视图。该 collection 受映射支持,
// 所以对映射的更改可在此 collection 中反映出来,反之亦然。
Iterator<String> it2 = values.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
/*
* 通过Map转成set就可以迭代。
* 找到了另一个方法。entrySet。
* 该方法将键和值的映射关系作为对象存储到了Set集合中,
* 而这个映射关系的类型就是Map.Entry类型(结婚证)
*/
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
// Set<Map.Entry<K,V>> entrySet()返回此映射中包含的映射关系的 Set 视图。该 set 受映射支持,
// 所以对映射的更改可在此 set 中反映出来,反之亦然。
Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
//此迭代器Iterator接受的是这个类型的引用对象:Map.Entry<Integer, String>
while(it.hasNext()){
Map.Entry<Integer, String> me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+"::::"+value);
}
//取出map中的所有元素。
//原理,通过keySet方法获取map中所有的键所在的Set集合,因为Set集合可以保证元素唯一性,
//在通过Set的迭代器获取到每一个键,在对每一个键通过map集合的get方法获取其对应的值即可。
/*
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()){
Integer key = it.next();
String value = map.get(key);
System.out.println(key+":"+value);
}
*/