舉個例子,假設我們要實做一個 List, 當索引值超出 List 長度時, 回傳傳入泛型型別的實例
C#
public class Animal
{
public override String ToString()
{
return this.GetType().Name;
}
}
public class Cat : Animal {}
public class Dog : Animal {}
public class Monkey : Animal {}
public class AnimalList<T> : List<T> where T : Animal
{
public new T this[int index]
{
get
{
if (index < this.Count)
{
return base[index];
}
else
{
return Activator.CreateInstance<T>();
}
}
set
{
base[index] = value;
}
}
}
public static void Main(string[] args)
{
AnimalList<Animal> a = new AnimalList<Animal>()
{
new Cat(),
new Dog(),
new Monkey()
};
for (int i = 0; i < 10; i++)
{
Console.WriteLine(a[i]);
}
}
C# 可利用傳入的 T 型別, 利用 reflection 建立物件實例Java
public class Animal
{
@Override
public String toString()
{
return this.getClass().getSimpleName();
}
}
public class Cat extends Animal {}
public class Dog extends Animal {}
public class Monkey extends Animal {}
public class AnimalList<T extends Animal> extends ArrayList<T>
{
private final Class<T> clazz;
public AnimalList(Class<T> clazz)
{
this.clazz = clazz;
}
@Override
public T get(int index)
{
T result = null;
if (index < size())
{
result = super.get(index);
}
else
{
try
{
result = this.clazz.newInstance();
}
catch (InstantiationException | IllegalAccessException e)
{
e.printStackTrace();
}
}
return result;
}
}
public static void main(String[] args)
{
final AnimalList<Animal> a = new AnimalList<Animal>(Animal.class)
{{
add(new Cat());
add(new Dog());
add(new Monkey());
}};
for (int i = 0; i < 10; i++)
{
System.out.println(a.get(i));
}
}
因 type erasure 的原因, 造成 JVM 在執行時期, 無法利用傳入的 T 型別, 建立物件實例, 所以必須在 constructor 傳入 Class 參數, 利用 Class 建立實例
參考 : http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createObjects
0 comments:
Post a Comment