1、Class對象的獲取有三種方式:
(1)任何類的對象可以通過調用Object類提供的**getClass()取得該類Class對象;
(2)類名稱.class可以直接根據某個具體類來取得其Class對象
(3)調用Class類的靜態方法Class.forName(String className)**傳入類的全名稱來取得其Class對象
且任何一個類的Class對象由JVM加載後產生(該Class對象在JVM中全局唯一)
public class Test1 {
public static void main(String[] args) {
/*根據類正向產生對象*/
Date date=new Date();
System.out.println(date);
/*
* 反射
* */
//1.類對象.getClass
System.out.println(date.getClass());
//2.類名稱.class
System.out.println(Date.class);
//3.Class.forName(String className)
try {
System.out.println(Class.forName("java.util.Date"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
/*任何一個類的class對象有且只有一個*/
System.out.println(date.getClass()==Date.class);//true
try {
System.out.println(date.getClass()==Class.forName("java.util.Date"));//true
System.out.println(Class.forName("java.util.Date")==Date.class);//true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2、根據反射取得一個類的Class對象後,可以通過反射來實例化對象,在Class類中有如下方法:
(1) public T newInstance() throws InstantiationException, IllegalAccessException
這種方法只能調用無參構造,並且無參構造必須是public權限;
方法是: 類對象.newInstance();
public class CreateObject {
public static void main(String[] args) throws Exception {
/*1.獲取類的Class對象*/
Class<?> cls=Class.forName("java.util.Date");
/*2.通過反射取得Date的實例化對象*/
Date date=cls.newInstance();
System.out.println(date);
}
}
(2)還有一種是Constructor類提供的實例化對象的方法:
public T newInstance(Object … initargs)
方法是:在使用newInstance之前,要先獲取構造方法Constructor,再對象.newInstance(…);括號內是要賦予對象屬性的值;
而要獲取本類中有參構造方法的方式有:
public Constructor getDeclaredConstructor(Class<?>… parameterTypes)
或者 public Constructor getConstructor(Class<?>… parameterTypes)
class Parent {
private String name;
private Integer age;
public Parent(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Parent{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class CreateObject2 {
public static void main(String[] args) {
Class<?> cls = Parent.class;
/*獲取構造方法*/
try {
//如果類中的構造方法是私有的,getDeclaredConstructor能夠拿到該構造方法,但是不能實例化對象
//要傳入獲取特定構造方法中的屬性的class對象
Constructor constructor = cls.getDeclaredConstructor(String.class, Integer.class);
Parent parent = (Parent) constructor.newInstance("張三", 14);//傳入實例化的屬性值
System.out.println(parent);
} catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
3.根據反射可以獲取類的方法
取得類中指定名稱的普通方法
public Method getMethod(String name, Class<?>… parameterTypes)
public Method getDeclaredMethod(String name, Class<?>… parameterTypes)
既要傳名稱又要傳類型,是因爲:方法有重載;
取得類中全部普通方法
public Method[] getMethods() throws SecurityException
:取得本類以及父類中所有public方法,
public Method[] getDeclaredMethods() throws SecurityException
:取得本類中所有全部普通方法,包含私有方法;
Method類中提供調用類中普通方法的API:
public Object invoke(Object obj, Object… args) 傳入實例化對象和獲取到的方法的參數值
//先獲取類對象
Class<?> cls= Per.class;
/*創建實例化對象*/
Per per= (Per) cls.newInstance();
/*拿到這個類中的setName的方法,傳入方法的名稱,如果該方法有參數,還要傳入參數的類型*/
Method method= cls.getMethod("setName", String.class);
/*通過invoke進行調用,invoke方法內要傳入創建好的實例化對象,如果該方法有參數再傳入要賦予該對象的值*/
method.invoke(per,"李四");