Java SE 基础:泛型

来源:互联网 发布:魔法盾软件 编辑:程序博客网 时间:2024/05/21 07:15
作者:小兔子脚
链接:https://zhuanlan.zhihu.com/p/25054132
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一:为什么要有泛型?

1.解决元素存储的安全问题。

2.解决获取元素时,需要进行类型强制转换。


二:泛型使用:

1.在集合中使用泛型:


2.自定义泛型类、泛型接口、泛型方法

1)自定义泛型类

①当实例化泛型类的对象时,指明泛型类的类型,指明后,对应的类中的所有使用泛型的位置,都变成实例化中指定的泛型的类型。

②如果自定义了泛型类,但在实例化时没有使用,那么默认的类型是 Object的。


②泛型接口 与 定义泛型类类似

③ 自定义泛型方法

1.当通过对象调用泛型方法时,需指明泛型方法的类型。

2.定义泛型方法时,必须要在返回值 T 前加一个<T> 来表明这是一个泛型方法。

3.格式:访问权限修饰符 <E> E 方法名(参数列表) {},E 不一定与 T 一个类型。

//此图借鉴Java中的泛型方法 - 杨元 - 博客园

(1)Class 有一个类型参数T,T 代表什么?他代表Class 对象代表的类型。

比如说,String.class 类型代表Class<String>,这样可以用来提高反射代码的类型安全。

(2)为什么要使用泛型方法呢?因为泛型类要在实例化的时候就指明类型,如果想换一种类型,不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候指明类型,更加灵活。

(3)参数T 和 Class<T > 以及 Class<?>的理解:


   单独的T 代表一个类型 而 Class<T>和Class<?>代表这个类型所对应的类
   Class<T>在实例化的时候,T要替换成具体类
   Class<?>它是个通配泛型,?可以代表任何类型
   public T find(Class<T> clazz, int id);
   根据类来反射生成一个实例,而单独用T没法做到




3.泛型与继承的关系
①继承泛型类或泛型接口时,可以指明泛型的类型。
②若不指明泛型的类型,需要在子类同样写上<T>
③若类A 是 类B 的子类,那么 List<A> 就不是 List<B> 的子接口。A、B 此时为并列关系,无论Object,String。。


4.通配符?
①List<A>、List<B>...都是List<?>的子类,A、B 此时为并列关系,无论Object,String。。
② ? extends A :可以存放A 及其子类
③ ? super A :可以存放A 及其父类

注意: 在Java集合框架中,对于参数值是未知类型的容器类,只能读取其中元素,不能像其中添加元素,
因为,其类型是未知,所以编译器无法识别添加元素的类型和容器的类型是否兼容,唯一的例外是NULL


5.泛型类 及 通配符 的使用注意点

1.静态方法中不能使用类的泛型。(static 在类实例化之前就已经存在了,但泛型还不确定)
2.如果泛型类是一个接口或抽象类,则不可创建泛型类的对象。
3.不能在catch 中使用泛型,就是不能用来修饰 e。
4.从泛型类派生子类,泛型类型需具体化。
5.把一个集合中的内容限制为一个特定的数据类型,这就是generics 背后的核心思想。

6.可以读取声明为 通配符 的集合类的对象。(都认为是Object 类型的)
7. 不允许向声明为 通配符的 集合类中写入对象。(不仅适用于集合类),不过可以往里面写null。
0 0