下边只是个人学习记录!
泛型
强制指定一个集合中存放元素的类型
public class A{
public static void main(String[] args) {
List<Animal> l = new ArrayList<>();
l.add(new Animal());
l.add("1"); // 在编译的时候会报错,因为使用泛型,集合中只能存放Animal类型的元素
}
}
class Animal{}
自定义泛型
使用自定义泛型的时候,<> 尖括号只是一个标识符,随便写,在调用的时候确定类型:
public class A{
public static void main(String[] args) {
Test<String> t = new Test<>();
t.say("大家好"); // 上边我们指定了say方法参数只能传String类型
Test<Integer> t1 = new Test<>();
t1.say(20); // 上边我们指定了say方法参数只能传整数类型
}
}
// T只是一个标识符
class Test<T>{
public void say(T o) {
System.out.println(o);
}
}
java源代码中,经常出现的是:
<E>和<T>
E:是element单词的首字母。
T:是type单词的首字母。
JDK8引入:自动类型推断机制(又称为钻石表达式)
下边list集合中使用了泛型,添加了2个类,后边 new ArrayList<> 就不需要添加类型了,会自动推断:
public class A{
public static void main(String[] args) {
List<Animal> list = new ArrayList<>();
l.add(new Animal());
l.add(new Dog());
}
}
class Animal{
public void say() {
System.out.println("动物在跑");
}
}
class Dog extends Animal {
public void cry() {
System.out.println("汪汪");
}
}
补充:
(0)优点:更加约束规范,减少出错机率;增强可复用。
(1)在编译时期明确类型:
ArrayList 使用的泛型时,如果在编译时期,必须要明确类型,否则在编译时期就不会通过!如:
上边代码,如果不使用泛型,编译时会通过,但是运行时出错了,如果使用泛型就不会发生类似错误!
(2)把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型。如下:
public class Test1<T> {
T name;
public Test1 (T name) {
this.name = name;
}
public T getName() {
return name;
}
public void setName(T name) {
this.name = name;
}
}
(3)泛型里的数据类型必须为引用类型。
因为虚拟机在编译时会把带泛型的转换成Object类型,而基本类型不属于Object类型,所以泛型里面数据类型不能是基本类型。
(4)在运行时期,泛型会失效,只存在于编译时期。
通过上面可知,泛型只在编译期有效,为什么运行期失效了呢,这是因为泛型的擦除概念,通俗点来说就是泛型的信息不会进行运行阶段。
public class Test {
public static void main(String[] args) throws Exception{
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("1");
Class<?> c = Class.forName("java.util.ArrayList");
Method m = c.getMethod("add", Object.class);
m.invoke(arrayList, 1);
System.out.println(JSON.toJSONString(arrayList));
}
}