Java中泛型的使用概述

时间:2022-10-10 19:25:08
java中的泛型使用概述
   泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为 泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的 情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的 强制类型转换,而这种转换是要求开发者对 实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况, 编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查 类型安全,并且所有的 强制转换都是自动和 隐式的,以提高代码的重用率。
规则限制:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的 泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass> “上界通配符(Upper Bounds Wildcards)”,表示参数化类型的可能是T 或是 T的子类
< T super superclass> “下界通配符(Lower Bounds Wildcards)”,表示参数化类型是此类型的超类型(父类型),直至Object。这两者习惯上称为“有界类型”。
5、泛型的参数类型还可以是 通配符类型。例如Class<?> classType = Class.forName("java.lang.String");
泛型包含3块内容:泛型类、泛型接口和泛型方法
 
1、泛型类
请看一下代码示例
没有用泛型:
public class NoFanClass {
    private Object ob; //用Object达到泛型效果
    
    public NoFanClass(Object ob){
        this.ob = ob;
    }
    public Object getob(){
        return ob;
    }
    
    public void showType(){
        System.out.println("E的实际类型是:"+ob.getClass().getName());
    }
}
 
public class NoFanMain {
    public static void main(String[] args){
        NoFanClass intob = new NoFanClass(1234);
        intob.showType();
        System.out.println("value"+intob.getob());
        
        NoFanClass strob = new NoFanClass("ABCD");
        strob.showType();
        System.out.println("value"+strob.getob());
        
    }
}
 
使用了泛型:
public class FanxingClass<E> {
    private E ob;   //定义泛型成员变量
    
    public FanxingClass(E ob){
        this.ob = ob;
    }
    public E getob(){
        return ob;
    }
    public void showType(){
        System.out.println("E的实际类型是:"+ob.getClass().getName());
    }
}
 
public class ClassMain {
    public static void main(String[] args){
        FanxingClass<Integer> intob = new FanxingClass(100);
        intob.showType();
        System.out.println("value"+intob.getob());
        System.out.println("----------------------------------");
        
        FanxingClass<String> strob = new FanxingClass("Jarvis");
        strob.showType();
        System.out.println("value"+strob.getob());
        
    }
}
这两个程序的输出结构都是:
 
E的实际类型是:java.lang.Integer
value100
----------------------------------
E的实际类型是:java.lang.String
valueJarvis

2、泛型接口
泛型接口的使用需要注意以下2点:
A.使用类实现泛型接口时类也写成泛型的,代码如下:
public interface Faninterface<E> {
    public E next();
}
 
public class Test<E> implements Faninterface<E> {          //在这个地方如果类不写成泛型的编译器会报错
    

    private String[] fruits = new String[]{"123","ABC","abc"};
    
    public E next() {
        Random rand = new Random();
        return (E) fruits[rand.nextInt(3)];
    }
  }
 
B.要么在类实现接口的时候指定具体的类型
public interface Faninterface<E> {
    public E next();
}
 
public class Test implements Faninterface<String> {             //这个地方已经将类型指定为String 
   
    private String[] fruits = new String[]{"123","ABC","abc"};         
    
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
  }
 
3.泛型方法
泛型方法,是在调用方法的时候指明泛型的具体类型,如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法
代码示例:
public class FanMethod {
    // 泛型方法 printArray   
    public static <E> void printArray(E[] inputArray){  //如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法
        for(E element:inputArray){    //inputArray是自定义的一个方法,按字符逐个输入数组
            System.out.printf("%s",element);  //格式化输出,s表示输出字符串
        }  
        System.out.println();  
    }  
      
    public static void main(String[] args) {  
         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.println("Array integerArray contains:");  
         printArray( intArray );//传递一个整型数组   
           
         System.out.println("\nArray doubleArray contains:");  
         printArray( doubleArray );//传递一个双精度型数组   
           
         System.out.println("\nArray characterArray contains:");  
         printArray( charArray );//传递一个字符型数组   
    }
}
 
总结:
1.泛型方法主要是用来解决Object的引用出现的“任意化”的问题,就是需要对类型强制转换,这样就有可能出现程序编译时没报错,而运行时报错的情况。
2.泛型接口的使用注意2点,要么在类实现泛型接口的时候把这个类也写成泛型的,要么在实现接口的时候在泛型接口处指定具体的类型,不用想肯定是第一种好用。
3.泛型方法的使用和泛型类的使用类似,但是泛型方法是在调用这个方法的时候才指定这个对象的类型。就是如果静态方法也要使用泛型,就必须要为这个静态方法加上泛型占位符<E>。