JAVA泛型

一.什么是泛型?

泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制

泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

错误的例子:

List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);
 
for(int i = 0; i< arrayList.size();i++){
    String item = (String)arrayList.get(i);
    Log.d("泛型测试","item = " + item);
}
List<String> arrayList = new ArrayList<String>();
...
//arrayList.add(100); 在编译阶段,编译器就会报错

二.泛型的特性

泛型只在编译阶段有效。
泛型信息不会进入到运行时阶段。

public class Demo1 {

	public static void main(String[] args) {
		List<String> stringArrayList = new ArrayList<String>();
		List<Integer> integerArrayList = new ArrayList<Integer>();
		 //getClass()返回的是对象运行时的类型
		Class classStringArrayList = stringArrayList.getClass();
		Class classIntegerArrayList = integerArrayList.getClass();
		 
		if(classStringArrayList.equals(classIntegerArrayList)){
		    System.out.print("泛型测试类型相同");
		}

	}

}

三.常用类型

  • E - Element (在集合中使用,因为集合中存放的是元素)
  • T - Type(表示Java 类,包括基本的类和我们自定义的类)
  • K - Key(表示键,比如Map中的key)
  • V - Value(表示值)
  • N - Number(表示数值类型)
  • ? – (表示不确定的java类型)
  • S、U、V - 2nd、3rd、4th types

四.泛型的使用

1.泛型类

泛型类:是在实例化类的时候指明泛型的具体类型
(1)使用语法
类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();

(2)Java1.7以后,后面的<>中的具体的数据类型可以省略不写
类名<具体的数据类型> 对象名 = new 类名<>(); 菱形语法

(3)注意事项

泛型类,如果没有指定具体的数据类型,此时,操作类型是Object
泛型的类型参数只能是类类型,不能是基本数据类型
泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;

    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}
public class GenericDemo {

	public static void main(String[] args) {
		//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
		//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
		Generic<Integer> genericInteger = new Generic<Integer>(123456);

		//传入的实参类型需与泛型的类型参数类型相同,即为String.
		Generic<String> genericString = new Generic<String>("key_vlaue");
		System.out.println("泛型测试key is " + genericInteger.getKey());
		System.out.println("泛型测试key is " + genericString.getKey());
     /*泛型测试key is 123456
       泛型测试key is key_vlaue*/

	}

}

泛型类的子类

  1. 子类也是泛型类,子类和父类的泛型类型要一致
  2. 子类不是泛型类,父类要明确泛型的数据类型

2.泛型接口

定义一个泛型接口

//定义一个泛型接口
public interface Generator<T> {
    public T next();
}

实现类不是泛型类,接口要明确数据类型

/**
 * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
 * 即:class FruitGenerator<T> implements Generator<T>{
 * 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class"
 */
class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}

实现类也是泛型类,实现类和接口的泛型类型要一致

/**
 * 传入泛型实参时:
 * 定义一个生产器实现这个接口,虽然只创建了一个泛型接口Generator<T>
 * 但是可以为T传入无数个实参,形成无数种类型的Generator接口。
 * 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
 * 即:Generator<T>,public T next();中的的T都要替换成传入的String类型。
 */
public class FruitGenerator implements Generator<String> {

    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}

3.泛型方法

泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型

泛型方法的基本介绍

  • @param tClass 传入的泛型实参
  • @return T 返回值为T类型
  • 说明:

1)public 与 返回值中间非常重要,可以理解为声明此方法为泛型方法。
2)只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法
3)表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。


public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}

静态方法与泛型

静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。
即:如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。

//静态方法方法,采用多个泛型类型
   public static <T, E, K> void printType(T t, E e, K k) {
     System.out.println(t + "\t" + t.getClass().getSimpleName());
     System.out.println(e + "\t" + e.getClass().getSimpleName());
     System.out.println(k + "\t" + k.getClass().getSimpleName());
   }

五.类型通配符

1、什么是类型通配符?

类型通配符一般是使用"?"代替具体的类型实参。所以,类型通配符是类型实参,而不是类型形参。

2、通配符上限

类/接口<? extends 实参类型> 要求该泛型的类型,只能是实参类型,或实参类型的子类类型

3、通配符下限

类/接口<? super 实参类型> 要求该泛型的类型,只能是实参类型,或实参类型的父类类型。

六.泛型与数组

可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象

import java.util.*;
public class Demo3 {

	public static void main(String[] args) {
		//不能直接创建带泛型的数组对象
	    //ArrayList<String>[] listArr = new ArrayList<>();
	    ArrayList<String>[] listArr = new ArrayList[5];
	 
	    ArrayList<Integer> intList = new ArrayList<>();
	    intList.add(100);
	 
	    ArrayList<String> strList = new ArrayList<>();
	    strList.add("jason");
	 
	    listArr[0] = strList;
	    String s = listArr[0].get(0);
	    System.out.println(s);
	}
}
import java.util.*;
import java.lang.reflect.Array;
public class Fruit<T> {
	private T[] array;
	 
	  public Fruit(Class<T> clz, int length) {
	    array = (T[])Array.newInstance(clz, length);
	  }
	 
	  public void put(int index, T item) {
	    array[index]=item;
	  }
	 
	  public T get(int index) {
	    return array[index];
	  }
	 
	  public T[] getArray(){
	    return array;
	  }
	  }

	public static void main(String[] args) {
		Fruit<String> fruit = new Fruit<>(String.class, 3);
	    fruit.put(0, "桃子");
	    fruit.put(1, "栗子");
	    fruit.put(2, "苹果");
	    System.out.println(Arrays.toString(fruit.getArray()));
	    String s1 = fruit.get(2);
	    System.out.println(s1);
	    }
	    /*[桃子, 栗子, 苹果]
         苹果*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值