泛型的优势和使用方法

Cold不叫寇德

为什么使用泛型

泛型类和泛型方法同时具备可重用性、类型安全和效率,这是非泛型类和非泛型方法无法具备的。 泛型通常用与集合以及作用于集合的方法一起使用。
可重用性:
比如要返回两个信息,一种是String类型的信息,一种是Integer类型的信息。
不使用泛型的话我们要添加两个方法,一个返回字符串,另一个返回数值类型 。

public String getString(String stringMessage){
        return stringMessage;
    }
    public Integer getInteger(Integer integerMessage){
        return  integerMessage;
    }

而使用泛型

public class Generic<T> {
    private T key;

    public Generic(T key) {
        this.key = key;
    }

    public T getKey() {
        return key;
    }
}

(如果用字符串和数值的强制转换,不使用泛型也可以用一个方法实现,但是有类型安全和高效率方面的问题)

类型安全:
先来看一下List的实现方式了。在List中可以放各种各样的数据类型,不论你push中的元素是什么,都变为Object类型。而且值类型向Object转换时,还得采取装箱操作,拿出来还得拆箱操作,很容易出现InvalidCastException异常。而泛型集合一旦声明了是何种数据类型的集合,就只能添加何种数据类型,不会转换成Object。
高效率
泛型集合一旦声明了是何种数据类型的集合,就只能添加何种数据类型。添加去也不会转换成Object,它是运行时动态的获取类型参数。也就是说没有装箱和拆箱这些操作。减少了处理器的资源浪费。

泛型的特性

泛型只在编译阶段有效。看下面的代码:

List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();

Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();

if(classStringArrayList.equals(classIntegerArrayList)){
    Log.d("泛型测试","类型相同");
}

输出结果:D/泛型测试: 类型相同。

通过上面的例子可以证明,在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。

泛型方法

泛型方法,是在调用方法的时候指明泛型的具体类型 。

下面的例子演示了如何使用泛型方法打印不同字符串的元素:

public class GenericMethodTest
{
   // 泛型方法 printArray                         
   public static < E > void printArray( E[] inputArray )
   {
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] )
    {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
 
        System.out.print( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组
 
        System.out.print( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.print( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}

编译以上代码,运行结果如下所示:

整型数组元素为:1 2 3 4 5

双精度型数组元素为:1.1 2.2 3.3 4.4

字符型数组元素为:H E L L O

类型通配符

类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List<String>,List<Integer> 等所有List<具体类型实参>的父类

public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        getData(name);
        getData(age);
        getData(number);
       
   }
 
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
}

输出结果为:

data :icon
data :18
data :314

泛型数组

在java中是”不能创建一个确切的泛型类型的数组”的。

下面的这个例子是不可以的,编译阶段会直接提示错误:

List<String>[] ls = new ArrayList<String>[10];  

而使用通配符创建泛型数组是可以的,如下面这个例子:

List<?>[] ls = new ArrayList<?>[10];  

这样也是可以的:

List<String>[] ls = new ArrayList[10];





阅读 1.8k
69 声望
4 粉丝
0 条评论
你知道吗?

69 声望
4 粉丝
宣传栏