文章目錄
1.反射是什麼?(W)
反射是運行中的程序檢查自己和軟件運行環境的能力,它可以根據它發現的進行改變。反射可以在運行時根據指定的類名獲得類的信息。(無需使用new 就能實例化對象)
2.爲什麼要有反射?(W)
利用反射,可以實現更好的解耦合操作。(代替new來實現對象實例化操作)
3.Object類中的getClass()方法:
作用:通過對象取得此對象所在類的信息。
當我們使用getClass方法時,返回的類型爲java.lang.class,這是反射操作的源頭類,即所有的反射操作都需要通過此類開始。
4.java.lang.Class類對象實例化:
有如下三種方法:
I.調用Object類中的getClass()方法,此類操作必須有實例化對象。
import java.util.Date;
public class Demo {
public static void main(String[] args) {
Date date = new Date();
Class<?> cls = date.getClass();
System.out.println(cls.getName());
}
}
java.util.Date
II.使用"類.class"取得,此時可以不用通過指定類的實例化對象取得
public class Demo {
public static void main(String[] args) {
Class<?> cls =java.lang.Object.class;
System.out.println(cls.getName());
}
}
java.lang.Object
III.調用Class類提供的方法:
public static 類<?> forName(String className)throws ClassNotFoundException
public class Demo {
public static void main(String[] args)throws Exception {
Class<?> cls =Class.forName("java.lang.Object");
System.out.println(cls.getName());
}
}
java.lang.Object
III中調用了Class類中forname()方法。
5.反射怎麼用?(H)
掌握了Class類對象實例化的三種操作形式,就可以利用Class類來進行類的反射控制了。
Class類中有如下重要方法:
public T newInstance()
throws InstantiationException,
IllegalAccessException
public static 類<?> forName(String name,
boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
最重要的就是newInstance()方法,作用是反射實例化對象。(不使用new也可以生成對象),此方法返回的類型爲Object。
如果要使用此方法反射實例化對象,則類中一定要提供無參構造方法。
利用反射實例化對象:
class Book {
public Book() {
System.out.println("*****這是無參構造");
}
@Override
public String toString() {
return "《*****》";
}
}
public class Demo {
public static void main(String[] args)throws Exception {
Class<?> cls =Class.forName("Book"); //設置要操作對象的類名稱
// 反射實例化後的對象返回的結果都是Object類型
Object obj = cls.newInstance(); //相當於使用new調用無參構造
Book book = (Book) obj; //向下轉型
System.out.println(book);
}
}
*****這是無參構造
《*****》
6.使用反射調用構造:
利用Class類的newInstance()方法可以實現反射實例化對象的操作,但是類中必須提供有無參構造方法。如果類中只提供有參構造方法時,就必須通過java.lang.reflect.Constructor類來實現對象的反射實例化操作。
另外,java.lang.reflect是所有反射操作類的程序包,類中的每一個結構都有相應的類進行操作定義,如:構造方法會使用Constructor類。
java.lang.Class類中取得類中的構造方法:
public Constructor<?>[] getConstructors()
//取得全部構造方法 throws SecurityException
public Constructor<T> getConstructor(類<?>... parameterTypes)
//取得指定參數類型的構造方法 throws NoSuchMethodException,
SecurityException
利用以上兩個方法可以取得java.lang.reflect.Construcor,而Constructor類的最重要的方法如下:
調用指定參數的構造實例化類對象
public T newInstance(Object... initargs)
throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
明確調用類中的有參構造方法:
import java.lang.reflect.Constructor;
class Book {
private String name;
private double price;
public Book(String name,double price){
this.name=name;
this.price=price;
}
@Override
public String toString() {
return "圖書名"+name +",價格"+price ;
}
}
public class Demo {
public static void main(String[] args)throws Exception {
Class<?> cls =Class.forName("Book"); //設置要操作對象的類名稱
//找到Book類中兩個參數的構造
Constructor<?> cst =cls.getConstructor(String.class,double.class);
Object obj =cst.newInstance("Java開發",66.6); //實例化對象,傳遞內容
System.out.println(obj);
}
}
以上程序首先利用Class類取得此構造方法,返回Constructor對象,然後利用Constructor類的newInstance()方法傳遞指定數據,就完成了對象的反射實例化。
7.反射調用方法:
java.lang.Class類取得普通方法的操作:
public 方法[] getMethods()
//取得類中的全部方法 throws SecurityException
public 方法 getMethod(String name,
//取得類中指定方法名稱與參數類型的方法 類<?>... parameterTypes)
throws NoSuchMethodException,
SecurityException
java.lang.reflect.Method類的最重要方法:
public Object invoke(Object obj,
Object... args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
8.反射調用成員:
java.lang.Class類中取得成員的操作:
//取得本類繼承父類的全部成員
public Field[] getFields()
throws SecurityException
//取得本類繼承父類中指定名稱的成員
public Field getField(String name)
throws NoSuchFieldException,
SecurityException
//取得本類定義的全部成員
public Field[] getDeclaredFields()
throws SecurityException
//取得本類指定名稱的成員
public Field getDeclaredField(String name)
throws NoSuchFieldException,
SecurityException
java.lang.reflect.Field類常用方法:
//取得該成員的類型
public 類<?> getType()
//取得指定對象成員中的內容,相當於直接調用成員
public Object get(Object obj)
throws IllegalArgumentException,
IllegalAccessException
//設置指定對象成員中的內容,相當於直接調用成員設置內容
public void set(Object obj,
Object value)
throws IllegalArgumentException,
IllegalAccessException
利用反射直接操作私有成員:
import java.lang.reflect.Field;
class Book {
private String name;
}
public class Demo {
public static void main(String[] args)throws Exception {
Class<?> cls =Class.forName("Book"); //取得反射對象
Object obj =cls.newInstance(); //實例化對象
Field titleField =cls.getDeclaredField("title");//取得類中的title屬性
titleField.setAccessible(true); //取消封裝
titleField.set(obj,"第一行代碼------");
System.out.println(titleField.get(obj));
}
}
titleField.setAccessible(true);作用就是取消封裝,如果沒有特殊需要儘量不適用這種。所有屬性訪問還是要通過setter、getter方法操作。
無論是使用反射調用普通還是方法類中的成員,都必須存在實例化對象,因爲類中的屬性必須在類產生實例化對象(有堆內存空間)後纔可以正常使用。