泛型
前面在编写动态数组类时,用到了泛型。
泛型,指参数化类型。比如:定义方法时有形参,然后调用此方法时传递的值是实参。参数化类型,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
泛型的特点:
1.泛型就是编写模板代码来适应任意引用数据类型,反省不支持基本数据类型。
2.使用时不必对类型进行强制转换
3.通过编译器对类型进行检查
4.使用泛型的类型支持向上转型
5.泛型实现方式是擦拭法
6.泛型通常适用于集合中
PS: 静态方法定义的泛型和类上的泛型没有任何关系
举简单例子:
其中 T,E表示不确定的变量类型,也可以写具体的类型 例如class Person{}
class Person<T, E>{}
擦拭法
所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。所以编译器内部永远把所有泛型 T 视为Object处理。正因 Object 无法持有基本数据类型,所以泛型不支持基本类型。
同类型使用不同的泛型, 类对象相同
List#getClass() == List#getClass()
此外。泛型 T 不能直接 new ,因为会解释成 new Object()
所以 可以借助 反射。反射后面再讲。
定义方法
class Student extends Person {}
注意: 父类的泛型是 真实类型
这里是使用父类的泛型,必须是真实类型
以上这些知识点的详细解读:
传送门
十分详细,加深理解
网页转载自博主:darrell007
Person类:
public class Person<T,E> {
T Name;
E Age;
public T getName() {
return Name;
}
public void setName(T name) {
Name = name;
}
public E getAge() {
return Age;
}
public void setAge(E age) {
Age = age;
}
}
以下测试类中的注释是个人理解:仅供参考。
测试类:
public class PersonTest {
// <? extends E> 只能传递其本身及其子类。
// 是 上限(Upper Bound)通配符,用来限制元素的类型的上限
@Test
public void addPerson(Person<String, ? extends Number> person){
System.out.println(person);
//————————————————————————设置————————————————————
/*
因为<? extends Number>只是告诉编译器集合中元素的类型上限,
但它的具体类型是不确定的可能是他本身 或者 他的子类 ,因此 编译器无法添加元素
*/
// person.setAge(Integer.valueOf(23));
// person.setAge((Number)2);
//——————————————————————取——————————————————————————
/*
无论persons指向什么,编译器都可以确定获取的元素是Animal类型,所有读取集合中的元素是允许的
*/
//通俗来说:现在你是Number,你儿子(子类)给你礼物,你知道礼物是谁给的,所以你可以拿
person.getAge();
}
@Test
public void setPerson(Person<String, ? super Integer> person){
System.out.println(person);
//————————————————————————设置————————————————————
/*
Person的第二个参数是Integer或 Integer的某个父类,但无法确定具体类型,
但是可以确定的是 Integer或 Integer的子类 是和这个“不确定的类”兼容的
因为它肯定是这个“不确定类型”的子类,因此只允许添加 Person 或者 Person子类 的对象
*/
person.setAge(20);
//——————————————————————取——————————————————————————
/*
编译器允许从person中获取元素的,
但是无法确定的获取的元素具体是什么类型,
只能确定一定是Object类型的子类,因此我们想获得存储进去的对应类型的元素就只能进行强制类型转换了
*/
//通俗来说:现在你是Integer,你父辈给了你很多物品,但是你不知道哪个是谁给的
// 而你的子类就是你的物品,你知道这些是你的
Integer age = (Integer)person.getAge();
}
@Test
public void test(){
PersonTest test = new PersonTest();
// Person<String,Integer> person = new Person<>("张三",Integer.valueOf(5));
//
// test.addPerson(person);
//
// Person<String,Object> person2 = new Person<>("兔子",3);
//
// test.setPerson(person2);
}
}