class building {}
class Maker<T> {
Class<T> kind;
Maker(Class<T> kind){
this.kind = kind;
}
T make() throws IllegalAccessException, InstantiationException {
return kind.newInstance();
}
}
public class test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
/*第一種方式*/
Class<?> fromFroName = Class.forName("building");
// Class<? extends building> fromFroName2 = Class.forName("building"); //解開註釋,編譯報錯
// Class<building> fromFroName3 = Class.forName("building"); //解開註釋,編譯報錯
/*第二種方式*/
Class<? extends building> fromGetClass = new building().getClass();
// Class<building> fromGetClass2 = new building().getClass(); //解開註釋,編譯報錯
/*第三種方式*/
Class<building> fromClass = building.class;
/*第四種方式*/
ClassLoader loader = new building().getClass().getClassLoader();
Class<?> fromLoadClass = loader.loadClass("building");
/*第五種方式*/
Maker<building> maker = new Maker<building>(fromClass);
Class<building> fromMakerKind = maker.kind;
building b = maker.make();
}
}
- 通過
Class.forName(類名)
獲得。但這種方式獲得的Class對象的泛型類型只能是通配符的,從下面的兩行註釋代碼可知,要想獲得更具體的泛型類型時,都會編譯報錯。 - 通過
對象.getClass()
獲得。這種方式獲得的Class對象的泛型類型,雖然比上一種更加具體,可以是Class<? extends building>
了,但不能具體到Class<building>
了。 - 通過
類名.class
獲得。這種方式獲得的Class對象的泛型類型,最具體,是Class<building>
。 - 通過
ClassLoader對象.loadClass("類名")
獲得。但這種方式獲得的Class對象,和第一種Class.forName(類名)
一樣,只能是通配符的泛型類型。 - 通過成員變量
Class<T> kind
獲得,注意Maker是一個自定義的泛型類(第五種其實和反射無關了)。因爲泛型指定了new Maker<building>
,所以構造器實際上變成了Maker(Class<building> kind)
,而對於傳入的fromClass而言,是符合構造器參數類型。不用擔心泛型機制的類型擦除會擦除掉Class<T> kind
裏的尖括號裏的信息,因爲在泛型代碼的出口處(比如maker.kind
)會自動強轉爲Class
爲Class<building>
。
關於第五種方式,還可以進行拓展,但需要理解泛型的相關知識:
Class<building> fromMakerKind1 = new Maker<building>(fromClass).kind;
// Class<building> fromMakerKind2 = new Maker<? extends building>(fromGetClass).kind;
Class<building> fromMakerKind2 = new Maker(fromGetClass).kind;
// Class<building> fromMakerKind3 = new Maker<?>(fromFroName).kind;
Class<building> fromMakerKind3 = new Maker(fromFroName).kind;
註釋掉的兩行代碼,取消註釋後,你會收穫一個編譯錯誤:Type parameter '? extends building' cannot be instantiated directly
或者Type parameter '?' cannot be instantiated directly
,這其實很簡單,在實例化的時候,泛型類型不允許爲帶通配符的,當然,除外構造器的其他方法是可以的。
你還會收穫兩個警告:
第一個警告告訴你:Maker對象以原生類型實例化了。
第二個警告告訴你:等號兩邊的賦值,是從原生類型轉型到了Class<building>
。