舉個例子,假設我們要實做一個 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