关于泛型

1:Java的泛型是类型擦除的。

    java的泛型在编译期有效,但是在运行期所有的类型参数都会被删除。

class example{
	public void arrayMethod(String[] strArray){}
	public void arraymethod(Integer[] intArray){}
	public void listMethod(List<String> strList){}
	public void listMethod(List<Integer> intList){}
}
这个例子编译会出错:Method listMethod(List<String>) has the same erasure listMethod(List<E>) as another method in type example


JAVA泛型在编译期,所有泛型类型都会转换,编译后的字节码是没有任何泛型信息的,也就是说:一个泛型类和一个普通类在编译后指向同一个字节码。这样做的原因:

1:泛型只存在编译期,而不在运行期,避免了JVM的大换血

2:版本兼容,在1.5以上的版本中,List这样的 原生类型也可以正常编译通过,只是会出现警告而已。

因为泛型是类型擦除的,所以:

1:泛型的class对象是相同的,每个类都有class属性,泛型化不会改变其返回值


class example2 {
	public void test() {
		List<String> list1 = new ArrayList<String>();
		List<Integer> list2 = new ArrayList<Integer>();
		System.out.println(list1.getClass() == list2.getClass());
	}
}
 2:泛型数组初始化时不能声明泛型类型



//	List<String>[] strList;
	List<String>[] strList =new List<String>[];
以上代码编译通不过,因为类型擦除。


3:instanceof不允许存在泛型参数


2:不能初始化泛型参数和数组

3:不同场景使用不同的泛型通配符

1:泛型结构只参与”读“的操作,则限定上限(extends关键字)

public static <E> void read(List<? extends E> list){
		for (E e : list) {
			//业务操作
		}
	}


可以推断出List中取出的是E类型的,具体类型在运行时才能确定,但是一定是一个确定的类型。

2:泛型结构只参与”写“的操作,则限定下限(super 关键字)


public static void write(List<? super Number> list){
		list.add(23);
		list.add(12.34);
	}
不用管是23这种Integer还是12.34这种Double类型,都可以加入到list中 ,因为他们都是Number类型的。


JDK中的一个例子Collections.copy方法来说明上限跟下限,它实现了把源列表中的所有元素拷贝到目标列表中对应的索引处。 

public static <T> void copy(List<? super T> dest, List<? extends T> src) {
        int srcSize = src.size();
        if (srcSize > dest.size())
            throw new IndexOutOfBoundsException("Source does not fit in dest");

        if (srcSize < COPY_THRESHOLD ||
            (src instanceof RandomAccess && dest instanceof RandomAccess)) {
            for (int i=0; i<srcSize; i++)
                dest.set(i, src.get(i));
        } else {
            ListIterator<? super T> di=dest.listIterator();
            ListIterator<? extends T> si=src.listIterator();
            for (int i=0; i<srcSize; i++) {
                di.next();
                di.set(si.next());
            }
        }
    }


源列表是用来提供数据的,所以src要用extends,目标列表是用来写入数据的,所以dest需要用super

如果既要读又要写,那么只需要用确定的泛型类型即可,如List<E>.



4:建议使用顺序:List<T>,List<?>,List<Object>

1:List<T>是一个确定的类型,只不过是在运行期确定而已

2:List<T>可以进行读写操作, add,remove等操作,因为固定类型为T,所以不需要转型。List<?>只读类型,因为我不能确定你到底是什么类型 ,这样就不安全了,List<?>取出的是Object类型,需要主动转型

4:只有上限由多重限定&,下限没有

5:不能在静态域或方法中引用类型变量

class example3<T>{
	private static T s;
	public static void method(T t){
		// do method
	}
}
出现编译错误 Cannot make a static reference to the non-static type T

 总而言之:

1:虚拟机中没有泛型,只有普通的类和方法。

2:所有的类型参数都用他们的限定类型替换

3:桥方法被合成来保持多态

4:为保持类型安全,必要时插入强制类型转换。 



一个泛型的实例

package generic;

import java.util.Date;
import java.util.GregorianCalendar;

public class PairTest3 {
	public static void main(String[] args) {
		Manager ceo = new Manager("Gus Greedy", 80000, 2003, 12, 15);
		Manager cfo = new Manager("Sid sneaky", 60000, 2003, 12, 15);
		Pair<Manager> buddies = new Pair<Manager>(ceo, cfo);
		printBuddies(buddies);

		ceo.setBonus(100000);
		cfo.setBonus(50000);
		Manager[] managers = { ceo, cfo };
		Pair<Employee> result = new Pair<Employee>();
		minmax(managers, result);
		System.out.println(result.getFirst().getName()
				+ result.getSecond().getName());
		maxminBonus(managers, result);
		System.out.println(result.getFirst().getName()
				+ result.getSecond().getName());
	}

	public static void printBuddies(Pair<? extends Employee> p) {
		Employee first = p.getFirst();
		Employee secend = p.getSecond();
		System.out.println(first.getName() + secend.getName());
	}

	public static void minmax(Manager[] a, Pair<? super Manager> result) {
		if (a == null || a.length == 0)
			return;
		Manager min = a[0];
		Manager max = a[0];
		for (int i = 0; i < a.length; i++) {
			if (min.getBonus() > a[i].getBonus())
				min = a[i];
			if (max.getBonus() < a[i].getBonus())
				max = a[i];
		}
		result.setFirst(min);
		result.setSecond(max);
	}

	public static void maxminBonus(Manager[] a, Pair<? super Manager> result) {
		minmax(a, result);
		PairAlg.swapHelper(result);
	}
}

class PairAlg {
	public static boolean hasNulls(Pair<?> p) {
		return p.getFirst() == null || p.getSecond() == null;
	}

	public static void swap(Pair<?> p) {
		swapHelper(p);
	}

	public static <T> void swapHelper(Pair<T> p) {
		T t = p.getFirst();
		p.setFirst(p.getSecond());
		p.setSecond(t);
	}
}

class Employee {
	private String name;
	private double salary;
	private Date hireDay;

	public Employee(String n, double s, int year, int month, int day) {
		name = n;
		salary = s;
		GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
		hireDay = calendar.getTime();
	}

	public void raiseSalary(double byPercent) {
		double raise = salary * byPercent;
		salary += raise;

	}

	public String getName() {
		return name;
	}

	public double getSalary() {
		return salary;
	}

	public Date getHirDay() {
		return hireDay;
	}
}

class Manager extends Employee {
	private double bonus;

	public Manager(String n, double s, int year, int month, int day) {
		super(n, s, year, month, day);
		bonus = 0;
	}

	public double getBonus() {
		return bonus;
	}

	public void setBonus(double bonus) {
		this.bonus = bonus;
	}

	public double getSalary() {
		double baseSalary = super.getSalary();
		return baseSalary + bonus;
	}

}

你可能感兴趣的:(java,泛型)