Java泛型全解析

把一个对象放进集合中以后,集合就会忘记这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成Object类型了java

 

为了解决上面的问题,就引出了泛型这一个概念ide

 

泛型接口和类

public class Fruit<T> {ui

private T info;this

 

public Fruit(T info) {spa

this.info = info;对象

}接口

 

public T getInfo() {内存

return info;get

}it

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit<String> lt = new Fruit<String>("苹果");

System.out.println(lt.getInfo());

Fruit<Integer> intg = new Fruit<Integer>(1);

System.out.println(intg.getInfo());

}

}

 

能够灵活的封装,而且同时有能够限定类型,泛型的接口和类更像是一种通用的模型,模型内部的类型由使用者本身限定

不管为泛型的类型形参传入哪种类型的实参,对于Java来讲,他们依然被当成同一个类处理,在内存中也只占用一块内存空间,所以在静态方法、静态初始化块或者静态变量的声明和初始化中不容许使用类型形参

 

泛型接口和类的子类

 

public class Apple extends Fruit<String>{

 

public Apple(String info) {

super(info);

}

 

@Override

public String getInfo() {

return super.getInfo();

}

 

}

 

  • 使用泛型接口或类的时候,虽然能够不加<>部分,可是推荐加上,否则还要强制类型转换等麻烦操做

  • 重写父类方法或者实现接口的时候,返回值必定要跟父类(接口)一致

 

设定类型形参的上限

 

public class Fruit<T extends String & java.io.Serializable> {

private T info;

 

public Fruit(T info) {

this.info = info;

}

 

public T getInfo() {

return info;

}

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit<String> lt = new Fruit<>("苹果");

System.out.println(lt.getInfo());

Fruit<?> intg = new Fruit<>("1");

System.out.println(intg.getInfo());

}

}

 

  • 能够有多个限定条件,存在多个限定条件的时候,使用&链接

  • 至多一个父类上限,多个接口上限

  • 接口上限要在类上线后面

 

类型通配符

 

使用类型通配符的类是各类该类的泛型的父类

 

public class Fruit<T> {

private T info;

 

public Fruit(T info) {

this.info = info;

}

 

public T getInfo() {

return info;

}

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit<String> lt = new Fruit<>("苹果");

System.out.println(lt.getInfo());

Fruit<?> intg = new Fruit<>(1);

System.out.println(intg.getInfo());

}

}

 

  • 在Java 7之后可使用菱形语法,在构造器后不须要完整的泛型信息

  • ?”用于操做具体的某个泛型类的时候,还未肯定最终使用时,采用的对象类型,就用问号做为占位的含义

 

通配符的上限设定

 

Fruit<? extends String> intg = new Fruit<>("1");

 

  • 使用extends的方式限定?必须是String类型或者是其子类类型

 

通配符的下限设定

 

static <T,B> void getCollection(Fruit<? super T>b){

System.out.println(b);

}

 

  • 必定要是T或者T的父类

 

泛型方法

 

修饰符<T,S>返回值类型 方法名(形参列表){

 

方法体

 

}

 

static <T,B> void getCollection(B[]b,Collection<T> c){

 

}

 

  • 多个类型形参之间用逗号分隔

  • 全部类型形参声明放在修饰符和方法返回类型之间

  • 方法中定义的类型形参只能在该方法里使用,而接口或类中定义的类型形参能够在整个接口、类中使用

  • 方法中的泛型参数无需显式传入实际类型参数

 

public class Fruit<T extends String & java.io.Serializable> {

private T info;

 

public Fruit(T info) {

this.info = info;

}

static <T,B> void getCollection(B[]b){

System.out.println(b);

}

public T getInfo() {

return info;

}

 

public void setInfo(T info) {

this.info = info;

}

 

public static void main(String[] args) {

Fruit.getCollection(new String[]{"1"});

}

}

 

  • 存在泛型构造器,不能使用”菱形“语法

 

泛型方法与类型通配符的区别

 

  • 泛型方法容许类型形参被用来表示方法的一个或多个参数之间的类型依赖关系,或者方法返回值与参数之间的类型依赖关系,若是没有这样的类型依赖关系,就不该该使用泛型方法

  • 类型通配符既能够在方法签名中定义形参的类型,也能够用于定义变量类型,但泛型方法中的类型形参必须在对应方法中显式声明

 

擦除和转换

 

擦除

 

当把一个具备泛型信息的对象赋值给另外一个没有泛型信息的变量时,尖括号中的泛型信息就会被擦除扔掉

 

转换

 

当把一个没有泛型信息的对象赋值给另外一个泛型信息的变量时,不会发生报错,会自动转换

相关文章
相关标签/搜索