在没有使用泛型的情况下,如果要实现参数“任意化”,通常会定义成Object类型来接受,然后强制类型转换使用;

而强制类型转换有明显的缺点,就是必须要知道实际参数的具体类型的情况才可以进行转换,同时在强制转换的过程中,编译器不会报错提示的,只有在运行阶段才会出现异常,一定程度上存在安全隐患。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数的方式传递,类似于方法中的变量参数。可以用在类、接口、方法的创建中,分别简称为泛型类、泛型接口、泛型方法。

一、泛型作用

为了解决Java容器无法记忆元素类型的问题;

在早期,如果将容器的元素类型设置为 Object 类,虽然什么类都能放进去,但是有以下问题。

a.取出元素的时候必须进行强制类型转换(尽管集合在运行时里面元素的“运行时类型”不变,即元素的getClass返回的还是最初自己的类型而不是Object);

b. 如果不小心往集合里加了不相同类型的元素可能会导致类型异常(进行equals、compare比较的时候尤为明显);

c. 由于没有类型就需要在很多地方进行强制类型转换,但是这样做增加了编程的复杂度,并且代码也不美观(臃肿),维护起来也更加困难;

所以泛型的作用就是

a.使集合定义元素类型,即取出元素的时候无需进行强制类型转化了,可以直接用原类型的引用接收;

b. 一旦指定了性参数那么集合中元素的类型就确定了,不能添加其他类型的元素,否则会直接编译保存,这就可以避免了“不小心放入其他类型元素”的可能;

c. 上述保证了如果在编译时没有发出警告,则在运行时就一定不会产生类型转化异常(ClassCastException);

二、 泛型的概念

定义

Java 5开始,引入了参数化类型(Parameterized Type)的概念,使Java集合实现泛型,允许程序在创建集合时就可以指定集合元素的类型,比如List就表名这是一个只能存放String类型的List;

使用

1、定义集合元素类型

定义泛型引用一定要使用尖括号指定类型参数,例如:List list、Map等,其中的String、Integer之类的就是类型参数;

其次,使用构造器构造泛型对象的时候可以指定类型参数也可以不指定,例如:

i. List list = new List();  // 这当然是对的
ii. List list = new List<>();  // 这样对,因为List的类型参数可以从引用推断出!

2、定义泛型类、接口:

使用 定义了该泛型类和接口的类型参数

public class Person { ... },
接口
public interface MyGneric {
E add(E val);
Set makeSet();
...
}

3、通配符和边界

extends T> 是指 “上界通配符(Upper Bounds Wildcards)
 super T> 是指 “下界通配符(Lower Bounds Wildcards)
 extends T>

比如:Plate, 只能使用 Fruit 的子类来定义泛型的实现类,

如果 Apple 是 Fruit 的子类,那就有如下

Plate extends Fruit> p=new Plate(new Apple());

java T 泛型修改属性值 java泛型t的作用_泛型

比如:

public Class Fruit(){}
public Class Apple extends Fruit(){}
public void test(? extends Fruit){};

测试

test(new Fruit());
test(new Apple());
test(new String()); //这个就会报错,
 super T>

比如 : Plate

java T 泛型修改属性值 java泛型t的作用_类型参数_02

3.1、上下界通配符的副作用

3.1.1、上界 extends T>不能往里存,只能往外取

3.1.2、 下界 super T>不影响往里存,但往外取只能放在Object对象里

3.2、PECS原则

频繁往外读取内容的,适合用上界Extends。

经常往里插入的,适合用下界Super。

-------------------------------------------------------------------------------------------