java泛型擦除的神秘之处,边界处的动作,擦除的补偿

java泛型擦除的神秘之处

package org.rui.generics.erasure;

public class HasF {
	public void f(){
		System.out.println("hasf.f");
	}

}
package org.rui.generics.erasure;
/**
 * 边界 <T extneds Hasf>声明T必须具有类型HasF或者从Hasf导出的类型。
 * 如果情况确实如此,那么就可以安全地在obj上调用f()了
 * T擦除了 HasF
 * @author lenovo
 *
 * @param <T>
 */
//class Manipulator<T>  Error: 不能调用obj.f()
 class Manipulator<T extends HasF>
 {
	private T obj;
	public Manipulator(T x){obj=x;}
	public void manipulate(){obj.f();}
	//获取泛型类型
	public T getGenType(){return obj;}

}

public class Manipulation<T>
{
	public static void main(String[] args)
	{
		HasF h=new HasF();
		Manipulator<HasF> man=new Manipulator<HasF>(h);
		man.manipulate();
		System.out.println("genType:"+man.getGenType().getClass());
	}
}
/**output:
hasf.f
genType:class org.rui.generics.erasure.HasF
*/
package org.rui.generics.erasure;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * 边界处的动作
 * 即失kind被存储为Class<T> 擦除也意味着它实际将被存储为 Class,没有任何参数
 * @author lenovo
 *
 */
public class ArrayMaker<T> {
	private Class<T> kind;
	public ArrayMaker(Class<T> kind)
	{
		this.kind=kind;
	}

	@SuppressWarnings("unchecked")
	T[] create(int size)
	{
		return (T[])Array.newInstance(kind, size);
	}

	public static void main(String[] args)
	{
		ArrayMaker<String> maker=new ArrayMaker<String>(String.class);
		String[] stringArray=maker.create(9);
		System.out.println(Arrays.toString(stringArray));
	}
}
/**output:
 * [null, null, null, null, null, null, null, null, null]
 */
package org.rui.generics.erasure;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 边界处的动作
 * 容器而不是数组 情况不不同了
 * @author lenovo
 *
 */
public class ListMaker<T> {
	/*private Class<T> kind;
	public ListMaker(Class<T> kind)
	{
		this.kind=kind;
	}*/

	List<T> create(T t,int n)
	{
		List<T> list= new ArrayList<T>();
		for(int i=0;i<n;i++)
			list.add(t);
		return list;
	}

	public static void main(String[] args)
	{
		ListMaker<String> maker=new ListMaker<String>();
		List<String> str=maker.create("hello",4);
		System.out.println(str);
	}
}
package org.rui.generics.erasure;
/**
 * 擦除的补偿
 *
 * 编译器将确保类型标签可以匹配泛型参数
 * @author lenovo
 *
 */

class Building{}
class House extends Building{}

public class ClassTypeCapture<T> {

	Class<T> kind;
	public ClassTypeCapture(Class<T> kind)
	{
		this.kind=kind;
	}

	public boolean f(Object obj)
	{
		System.out.println(kind +"   isInstance    "+obj);
		return kind.isInstance(obj);
	}

	public static void main(String[] args)
	{
		ClassTypeCapture<Building> ctc=
				new ClassTypeCapture<Building>(Building.class);
		System.out.println(ctc.f(new Building()));
		//父类  与子对比
		System.out.println(ctc.f(new House()));

		ClassTypeCapture<House> ctc2=
				new ClassTypeCapture<House>(House.class);
		//House is building 子对比父=false
		System.out.println(ctc2.f(new Building()));
		System.out.println(ctc2.f(new House()));

	}

}
/**
output:
true
true
false
true
*/
package org.rui.generics.erasure;
/**
 * 创建类型实例
 *
 * @author lenovo
 *
 */

class ClassAsFactory<T>
{
	 T x;
	 public ClassAsFactory(Class<T> kind)
	 {
		 try {
			x=kind.newInstance();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	 }
}

////////////////////////////////////
class Employee{}

public class InstantiateGenericType {
	public static void main(String[] args)
	{
		ClassAsFactory<Employee> caf=
				new ClassAsFactory<Employee>(Employee.class);
		System.out.println("caf:"+caf.x);

		/*try {
		 //Integer 没有默认的构造器
			ClassAsFactory<Integer> cafInt=
					new ClassAsFactory<Integer>(Integer.class);
		} catch (Exception e) {
			System.out.println("ClassAsFactory<Integer> failed");
		}*/

	}

}
package org.rui.generics.erasure;

interface FactoryI<T>
{
	T create();
}

class Foo2<T>
{
	private T x;
	public <F extends FactoryI<T>> Foo2(F f)
	{
		x=f.create();
	}
}

///////////////////////////////////////////////////////////////////
class IntegerFactory implements FactoryI<Integer>
{
	public Integer create()
	{
		return new Integer(0);
	}

}
///////////////////////////////////////////////////////////////////
class Widget
{
  public static class Factory implements FactoryI<Widget>
  {
		public Widget create()
		{
			return new Widget();
		}
   }
}
///////////////////////////////////////////////////////////////////
public class FactoryConstraint {
	public static void main(String[] args)
	{
		new Foo2<Integer>(new IntegerFactory());
		new Foo2<Widget>(new Widget.Factory());
	}
}
package org.rui.generics.erasure;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Frob{}
class Fnorkle{}
class Quark<Q>{}
class Particle<POSITION,MOMENTUM>{};
/**
 * java 泛型是使用擦除来实现的
 * 在泛型代码内部,无法获得任何有关泛型 参数类型信息
 * @author lenovo
 *
 */

public class LostInformation {
	 public static void main(String[] args)
	 {
		 List<Frob> list=new ArrayList<Frob>();
		 Map<Frob,Fnorkle> map=new HashMap<Frob,Fnorkle>();
		 Quark<Fnorkle> quark=new Quark<Fnorkle>();
		 Particle<Long,Double> p=new Particle<Long,Double>();

		 System.out.println(Arrays.toString(
				 list.getClass().getTypeParameters()));

		 System.out.println(Arrays.toString(
				 map.getClass().getTypeParameters()));

		 System.out.println(Arrays.toString(
				 quark.getClass().getTypeParameters()));

		 System.out.println(Arrays.toString(
				 p.getClass().getTypeParameters()));
	 }
}
/*output:
[E]
[K, V]
[Q]
[POSITION, MOMENTUM]
*/

java泛型擦除的神秘之处,边界处的动作,擦除的补偿,布布扣,bubuko.com

时间: 2024-10-15 10:57:14

java泛型擦除的神秘之处,边界处的动作,擦除的补偿的相关文章

Java泛型:类型擦除

类型擦除 代码片段一 Class c1 = new ArrayList<Integer>().getClass(); Class c2 = new ArrayList<String>().getClass(); System.out.println(c1 == c2); /* Output true */ 显然在平时使用中,ArrayList<Integer>()和new ArrayList<String>()是完全不同的类型,但是在这里,程序却的的确确会输

java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题

java泛型(二).泛型的内部原理:类型擦除以及类型擦除带来的问题 参考:java核心技术 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首要前提是理解类型擦出(type erasure). Java中的泛型基本上都是在编译器这个层次来实现的.在生成的Java字节码中是不包含泛型中的类型信息的.使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉.这个过程就称为类型

Java泛型擦除

Java泛型擦除: 什么是泛型擦除? 首先了解一下什么是泛型?我个人的理解:因为集合中能够存储随意类型的对象.可是集合中最先存储的对象类型一旦确定后,就不能在存储其它类型的对象了,否则,编译时不会报错.但执行时会抛出ClassCastException异常.为解决此问题,引入泛型,指定该集合对象中存储的对象类型,这样一旦该集合中存储了其它的对象类型,编译时会提示错误!(理解不当之处.希望大神多指点). 泛型的擦除就是说.在编译的时候集合中指定了确定的对象类型,但在执行时将集合中能够存储的该对象类

java泛型边界深入探讨,示例代码

package org.rui.generics.bounds; import java.awt.Color; /** * 边界 * 下面展示了边界基本要素. * @author lenovo * */ interface HasColor{java.awt.Color getColor();} class Colored<T extends HasColor> { T item; Colored(T item){this.item=item;} T getItem(){return item

转:有关Java泛型的类型擦除(type erasing)

转载自:拈花微笑 自从Java 5引入泛型之后,Java与C++对于泛型不同的实现的优劣便一直是饭后的谈资.在我之前的很多training中,当讲到Java泛型时总是会和C++的实现比较,一般得出的结论是 Java使用类型擦除(type erasing),泛型信息只在编译时供javac作类型检查用,在编译后便被javac擦除,因此无法被反射 C++使用代码模板实现泛型,即在预处理时会生成类似?list_int?,?list_char?等的泛型类,虽然解决Java的运行时伪泛型的问题,但是会导致编

Java泛型之类型擦除

类型擦除 学过C++模板的,在使用Java泛型的时候,会感觉到有点不疑问,例如:(1)无法定义一个泛型数组.无法调用泛型参数对象中对应的方法(当然,通过extends关键字是可以做到,只是比较麻烦):(2)ArrayList<Integer>和ArrayList<String>在运行时的类型是相同的.Java中的泛型有这些问题,是它的实现机制决定的,即"类型擦除". 类型擦除的定义:编译通过后,准备进入JVM运行时,就不再有类型参数的概念,换句话说:每定义一个泛

【转载】Java泛型(一)

转自:http://www.cnblogs.com/lzq198754/p/5780426.html 1.为什么需要泛型 泛型在Java中有很重要的地位,网上很多文章罗列各种理论,不便于理解,本篇将立足于代码介绍.总结了关于泛型的知识.希望能给你带来一些帮助. 先看下面的代码: List list = new ArrayList(); list.add("CSDN_SEU_Cavin"); list.add(100); for (int i = 0; i < list.size(

Java 泛型(Generics) 综述

一. 引子 一般的类和方法,只能使用具体类型:要么是基本类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 多态算是一种泛化机制,但对代码的约束还是太强(要么继承父类,要么实现接口). 有许多原因促成了泛型的出现,而最引人注目的一个原因,就是为了创造容器类.(泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性) 例如,在 Java 实现加入泛型前,ArrayList 只维护一个 Object 类型的数组: publ

Java:泛型基础

泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的三种方法: 1.多态:将方法的参数类型设为基类,那么该方法就可以接收从这个基类导出的任何类作为参数. class Primary{} //定义基类 class Test() { public void f(Primary p) {...} } 2.方法的参数使用接口:任何实现了该接口的类都可以满足该