public Class Erased<T>{
private final int SIZE = 100;
public static void f(Object arg){
if(arg instanceof T){} // Error
T var = new T(); // Error
T[] array = new T[SIZE]; // Error
T[] array = (T)new Object[SIZE]; // Unchecked warning
}
}
Erased.java 中创建类型实例无法实现,部分原因是因为擦除,而另一部分 原因是因为编译器不能验证T具有默认(无参)构造器。 Java中的解决方案是传递一个工厂对象,并使用它来创建新的实例。最便利的 工厂对象就是Class对象, 因此如果使用类型标签,就可以使用newInstance() 来创建这个类型的新对象
class ClassAsFactory<T>
{
T x;
public ClassAsFactory(Class<T> kind){
try{
x = kind.newInstance():
}catch(Exception e){
...
}
}
}
class Employee{}
public class InstantiateGenericType
{
public static void main(String[] args){
ClassAsFactory<Employee> fe =
new ClassAsFactory<Employee>(Employee.class);
try{
ClassAsFactory<Integer> f1 =
new ClassAsFactory<Integer>(Integer.class);
}catch(Exception e){
...
}
}
}
可以编译,但是会因为ClassAsFactory<Integer>而失败,因为Integer没有任何 默认的构造器。 因为这个错误不是在编译期捕获的,所以不赞成,建议使用显式 的工厂,并将限制其类型,使得只能接受实现了这个工厂的类。
interface Factory1<T>
{
T create();
}
class Foo2<T>
{
private T x;
public <F extends Factory1<T>> Foo2(F factory){
x = factory.create();
}
}
class IntegerFactory implements Factory1<Integer>
{
public Integer create(){
return new Integer(0);
}
}
class Widget
{
public static class Factory implements Factory1<Widget>
{
public Widget create(){
return new Widget();
}
}
}
public class FactoryConstrain
{
public static void main(String[] args){
new Foo2<Integer>(new IntegerFactory());
new Foo2<Widget>(new Widget.Factory())
}
}
这只是传递Class<T>的一种变体, 2种方式都传递了工厂对象, Class<T>碰巧是
内建的工厂对象,而上面的方式创建了一个显式的工厂对象,但却获得了编译器检查。
另一个种方式是模板方法法设计模式,get()是模板方法,而create()是在子类
中定义的,用来产生子类类型的对象。
abstract class GenericWithCreate<T>
{
final T element;
GenericWithCreate(){
element = create();
}
abstract T create();
}
class X{}
class Creator extends GenericWithCreate<X>
{
x create(){
return new X();
}
void f(){
sysout(element.getClass().getSimpleName());
}
}
public class CreatorGeneric
{
public static void main(String[] args){
Creator c = new Creator();
c.f();
}
}