我认为泛型可理解为类的形参(类似方法的参数)。当定义了泛型以后,就可通过不同类型参数的构造方法声明该类的对象。该形参可以传入任何Object
public class Main_01 {
public static void main(String[] args) {
//先拿list举例
List<String> list = new ArrayList<String>();
list.add(2);//此处会出红线,因为上一行约定好必须要为String对象
list.add("2");//正常,后面在使用的时候便不需要加类型转换
//自己举的例子
Test<Main_01> m = new Test<Main_01>(new Main_01());
}
//下面这个方法的定义会报错。。看来方法的定义必须要明确参数类型。不能使用泛型
public void TestMethod(E name){
}
}
//类的形参E
class Test<E> {
private E element;
public Test(E element) {
this.element = element;
}
public E getElement() {
return element;
}
public void TestMethod(E name) {
}
}
但是从上面这个例子并没有看出来出来泛型的好处
从HashMap的源码来看:
//声明HashMap类,可忽略父类和引入的接口
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable{}
//put方法
public V put(K key, V value) {}
//get方法
public V get(Object key) {}
在声明HashMap的时候有感受到泛型的帮助么!确实有帮助,例:
//1.没有约束的声明
HashMap hm1 = new HashMap();
hm1.put("s", "B");
hm1.put("b", 2);//what?你让我get出来你干啥!
//2.声明好边具有约束作用
HashMap<String, HashMap<String,String>> hm = new HashMap<String, HashMap<String,String>>();
hm.put("Key","报错例子")
HashMap<String,String> Value = new HashMap<String, String>();
hm.put("Key", Value);//正确例子
如代码所示:hm1对象的get方法并不知道Value的类型。而hm对象的get方法可以放心使用!因为不是HashMap类型的方法根本没有办法put进去!
综上所述:泛型的好处列出来了!(fuck?你确定能看出来这么多好处,还有这些都是啥好处啊。。。)
Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型在使用中还有一些规则和限制:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(Java.lang.String);
Java泛型中的标记符含义:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
S、U、V - 2nd、3rd、4th types
上面说到HashMap里面有这么一个构造方法:
public HashMap(Map<? extends K, ? extends V> m) {}
忍不住百度了一下:
原来是通配符:
通配符有三种:
1、无限定通配符 形式<?>
2、上边界限定通配符 形式< ? extends Number> //用Number举例
3、下边界限定通配符 形式< ? super Number> //用Number举例
1:界定通配符的上边界
Vector<? extends 类型1> x = new Vector<类型2>();
类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的子类
Vector<? extends Number> x = new Vector<Integer>();//这是正确的
Vector<? extends Number> x = new Vector<String>();//这是错误的
2:界定通配符的下边界
Vector<? super 类型1> x = new Vector<类型2>();
类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的父类
Vector<? super Integer> x = new Vector<Number>();//这是正确的
Vector<? super Integer> x = new Vector<Byte>();//这是错误的