泛型的使用
泛型的好处:
泛型可以为集合规定元素类型,一旦集合规定了元素类型那么集合中就只能保存和操作这种泛型规定的类型。
其他类型的的元素不能加入到集合中了。第一保证了集合中的元素的安全,第二,由于类型规定,那么从集合中获取元素的时候不需要强转了,但是请注意迭代器需要单独指定泛型,这个泛型必须跟集合的泛型一致。
代码:
Map<String, String> map = new HashMap<>();
map.put("班长", "黑椒");
map.put("体委", "狗莫");
map.put("学委", "狗智");
Iterator<String> iterator = map.keySet().iterator();
while(iterator.hasNext()){
String key = iterator.next();
String s = map.get(key);
System.out.println(s);
泛型的概念:
类型参数,传统情况下,传参的时候只能传递对象。泛型就是在传参的时候可以传递类。
泛型可以使用在集合的定义和使用,类的定义,接口的定义,方法的定义上。
自定义泛型:自定义泛型可以类,接口和方法。
自定义泛型的类
代码:
public class Test<T>{
private T test;
public T test(){return null;}
public T test(T t){return null;}
public void test2(T t){}
}
1.这个泛型的T可以用任何字母,但是习惯上用T,是Type的首字母。
2.泛型的T是在创建对象的时候指定具体类型
MyData data = new MyData();
3.泛型不能用于修饰static的成员。因为泛型是在创建对象的时候体现出来的。
自定义泛型的接口
public interface MyIntOne<T> {
public void methodOne(T t);
public T methodTwo();
public T mehtodThree(T t);
}
定义的泛型接口的泛型确定第一种方式:
public class MyIntOneImpl implements MyIntOne<String, Integer> {}
实现类在实现接口的时候直接指定泛型类型
定义的泛型接口的泛型确定第二种方式:
public class MyIntOneImplTwo<T, U> implements MyIntOne<T, U> {}
实现类在实现接口的时候不给出泛型的类型,实现类也变成泛型的。那么这个泛型的实现类在创建对象的时候给出泛型的类型
MyIntOne<Double,Long> one = new MyIntOneImplTwo<>();
泛型的方法:
类不是泛型的,方法却可以使用泛型。
public class GenericMethod {
public<T> void testOne(T t){
System.out.println(t.getClass().getName());
}
}
GenericMethod gm = new GenericMethod();
gm.testOne(20);
调用泛型的方法的时候,传递的参数是什么类型,那么这个泛型就是确定为那个类型。
泛型的继承
泛型没有多态
在没有<? extends> 和 <? super>的情况下,左右两边的泛型必须是一致的。就算是有继承关系也不成立。
占位符“?”的使用
<? > ?代表占位符,表示它是一个泛型的集合
<? extends>表示本类以及它的子类和子类的子类可以往集合里面放,这种方式规定了集合的上限。
代码:
public void Test(List<? extends Animal> list){
for (Animal animal : list) {
System.out.println(animal);
}
}
<? super>表示本类以及它的父类和父类的父类可以往集合里面放,这种方式规定了集合的下限。
代码:
public void Test(List<? super Animal> list){
for (Object animal : list) {
System.out.println(animal);
}
}
注意:两者遍历的区别就是类型的接收,要用最高级的父类接收。