Lion X

*浅谈Java中的泛型 * <Excerpt in index | 首页摘要>
Java中的泛型、泛型类、泛型方法

<The rest of contents | 余下全文>

泛型

为什么使用泛型

  • 存储在集合中的元素,取出来都是Object类型的,此时就得强转
  • 约束存储到集合中的元素必须是相同的数据类型
  • 设计一个点类,来封装坐标位置,要求坐标位置支持String支持integer支持double类型(重复设计)

泛型(Generic Type)

从Java5开始支持的新语法

什么是泛型

  • 广泛通用的类型
  • 代码模板中类型不确定,谁调用该段代码,谁指明类型

简单定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Demo<T>{
private T x;
private T y;
public T getX(){
return x;
}
public void setX(T x){
this.x = x;
}
public T getY{
return y;
}
public void setY(T y){
this.y = y;
}
}
//泛型尖括号中可以使用T:Type E:Element K:Key V:Value
//具体是什么类型取决于调用者,不对泛型进行设置默认object
public class TestDemo{
public static void main(String[]args){
Point<String> p1 = new Point<String>();
Point<Integer> p2 = new Point<Integer>();
}
}

泛型类

直接在类/接口上定义的类型

泛型类的子类继承泛型类是需要指定类型

使用泛型:保证前后类型一致

1
2
List<String> list = new ArrayList<String>();
//该list只能存储String类型的元素

因为前后类型相同,所以Java7开始,推出了泛型的菱形语法<>

1
List<String> list = new ArrayList<>();

泛型不存在继承的关系,例如:

1
List<Object>list = new ArrayList<String>();//错误的

从此以后,使用集合都得使用泛型来约束该集合中的元素的类型

通过反编译发现:泛型也是语法糖,底层依然使用强制类型转换的方式实现

泛型方法

在方法上声明泛型

  • 泛型类中的泛型只能适用于非静态方法,如果需要给静态方法设置泛型,此时使用泛型方法
  • 泛型类中的泛型应该适用于整个类中的多个方法,有时候支队某一个方法设置泛型即可

一般的,把自定义的泛型作为该方法的返回类型才有意义,而且此时的泛型必须是由参数设置进来的,如果没有参数来设置泛型的具体类型,此时的方法一般返回设计为Object即可

代码示例

1
2
3
4
//表示在该方法中使用T来表示一种未知类型
public static <T> T Demo(T value){
return value;
}

泛型的通配符、上限和下限

  • 泛型的通配符:不知道用什么类型来接收时,此时可以使用?,?表示未知通配符

    1
    2
    3
    4
    5
    6
    7
    8
    public class Demo{
    public static void main(String[]args){

    }
    private static void function(List<?>list){
    //此时只能接收数据,不能添加数据至list
    }
    }
  • 泛型的上限和下限:用来限定元素的类型必须时X类的子类或相同,X类的父类或相同

    1
    2
    3
    4
    5
    6
    7
    8
    //泛型的上限:此时的泛型?必须时Numer类型或Number类的子类
    public static void function(List<? extends Number> list){

    }
    //泛型的下限:此时的泛型?必须时Number类型或Number类的父类
    public static void function(List<? super Number>list){

    }

泛型的擦除和转换

  • 泛型的擦除:

    1. 泛型编译之后就消失了(泛型的自动擦除)

    2. 当把带有泛型的集合赋给不带泛型的集合,此时泛型被擦除(手动擦除)

      1
      2
      3
      4
      5
      6
      7
      8
      public class Demo{
      public static void main(String[]args){
      List<Integer> list1 = new ArrayList<>();
      list1.add(1);
      List list2 = null;
      list2 = list1;//此时泛型擦除
      }
      }
  • 堆污染:

    当一个方法既使用泛型的时候也使用可变参数,此时容易导致堆污染问题。

    如:在Arrays类中的 asList() 方法

 Comments