Java的反射(reflection)機制是指在程式的執行狀態中,可以構造任意一個類的物件,可以瞭解任意一個物件所屬的類,可以瞭解任意一個類的成員變數和方法,可以呼叫任意一個物件的屬性和方法。這種動態獲取程式資訊以及動態呼叫物件的功能稱為Java語言的反射機制。反射被視為動態語言的關鍵
根據組態檔 re.properties 指定資訊,建立 Cat 物件並呼叫方法 hi
classfullpath=com.jwt.Cat
method=hi
這樣的需求在學習框架時很多,即在通過外部檔案設定,在不修改原始碼的情況下,來控制程式。
傳統的方法是先 new 一個物件,然後再呼叫它的方法。
Cat cat = new Cat();
cat.hi();
通過傳統方法,確實可以呼叫 hi() 方法,但是這和我們的需求不一樣,這裡我們是要根據組態檔 re.properties 指定資訊來完成。可以使用 Properties 來讀取組態檔。
Properties properties = new Properties();
properties.load(new FileInputStream("src//re.properties"));
String classfullpath = properties.getProperty("classfullpath");//"com.jwt.Cat"
String methodName = properties.getProperty("method");//"hi"
System.out.println("classfullpath=" + classfullpath);
System.out.println("method=" + methodName);
然後需要建立物件,怎麼建立物件呢?直接new classfullpath
,這樣不就好了嘛?嗯,想法不錯,下回不要想了。現在的 classfullpath 可是字串型別,怎麼能去new
呢。所以現有技術是做不到這個事情的。那麼這裡就要引入我們要將的重點——反射機制。
public class ReflectionQuestion {
public static void main(String[] args) throws Exception {
//1. 使用Properties 類, 可以讀取組態檔
Properties properties = new Properties();
properties.load(new FileInputStream("src//re.properties"));
String classfullpath = properties.getProperty("classfullpath");//"com.jwt.Cat"
String methodName = properties.getProperty("method");//"hi"
System.out.println("classfullpath=" + classfullpath);
System.out.println("method=" + methodName);
//2. 使用反射機制解決
//(1) 載入類, 返回Class型別的物件cls
Class cls = Class.forName(classfullpath);
System.out.println("cls = " + cls);
//(2) 通過cls得到你載入的類com.jwt.Cat的物件範例
Object o = cls.newInstance();
System.out.println("o 的執行型別=" + o.getClass()); //執行型別
//(3) 通過cls得到你載入的類com.jwt.Cat的methodName "hi" 的方法物件
Method method = cls.getMethod(methodName);
//(4) 通過method 呼叫方法: 即通過方法物件來實現呼叫方法
method.invoke(o); //傳統方法物件.方法() , 反射機制:方法.invoke(物件)
}
}
反射機制還有一個優點,那就是可以通過外部檔案設定,在不修改原始碼的情況下,來控制程式。比如這裡,我在Cat 類下面再寫一個方法,cry()方法,如果我們使用傳統方法,要呼叫這個方法,是不是就要修改程式碼了,比如cat.cry();
通過反射,只需在組態檔 re.properties 中,將 method=hi 改為 method=cry 就可以了。
一句話總結:反射就是在執行時才知道要操作的類是什麼,並且可以在執行時獲取類的完整構造,並呼叫對應的方法。動態特性
package com.jwt.reflection;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
public class Reflection01 {
public static void main(String[] args) throws Exception {
//1. 使用Properties 類, 可以讀寫組態檔
Properties properties = new Properties();
properties.load(new FileInputStream("src//re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String methodName = properties.get("method").toString();
//2. 使用反射機制解決
//(1) 載入類, 返回Class 型別的物件cls
Class cls = Class.forName(classfullpath);
//(2) 通過cls 得到你載入的類com.hspedu.Cat 的物件範例
Object o = cls.newInstance();
System.out.println("o 的執行型別=" + o.getClass()); //執行型別
//java.lang.reflect.Method:代表類的方法,Method 物件表示某個類的方法
Method method = cls.getMethod(methodName);
//通過method 呼叫方法: 即通過方法物件來實現呼叫方法
method.invoke(o);
//java.lang.reflect.Field: 代表類的成員變數, Field 物件表示某個類的成員變數
//getField 不能得到私有的屬性
Field nameField = cls.getField("name");
System.out.println(nameField.get(o)); // 傳統寫法物件.成員變數, 反射: 成員變數物件.get(物件)
//java.lang.reflect.Constructor: 代表類的構造方法, Constructor 物件表示構造器
Constructor constructor = cls.getConstructor(); //()中可以指定構造器引數型別, 返回無參構造器
System.out.println(constructor);//Cat()
Constructor constructor2 = cls.getConstructor(String.class); //這裡傳入的String.class 就是String 類的Class 物件
System.out.println(constructor2);//Cat(String name)
}
}
反射呼叫優化-關閉存取檢查
package com.jwt.reflection;
import com.jwt.Cat;
import java.lang.reflect.Method;
public class Reflection02 {
public static void main(String[] args) throws Exception {
m1();//傳統
m2();//反射
m3();//反射優化
}
//傳統方法來呼叫hi
public static void m1() {
Cat cat = new Cat();
long start = System.currentTimeMillis();
for (int i = 0; i < 900000000; i++) {
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("m1() 耗時=" + (end - start)+"ms");
}
//反射機制呼叫方法hi
public static void m2() throws Exception {
Class cls = Class.forName("com.jwt.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long start = System.currentTimeMillis();
for (int i = 0; i < 900000000; i++) {
hi.invoke(o);//反射呼叫方法
}
long end = System.currentTimeMillis();
System.out.println("m2() 耗時=" + (end - start)+"ms");
}
//反射呼叫優化+ 關閉存取檢查
public static void m3() throws Exception {
Class cls = Class.forName("com.jwt.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
hi.setAccessible(true);//在反射呼叫方法時,取消存取檢查
long start = System.currentTimeMillis();
for (int i = 0; i < 900000000; i++) {
hi.invoke(o);//反射呼叫方法
}
long end = System.currentTimeMillis();
System.out.println("m3() 耗時=" + (end - start)+"ms");
}
}
/**
m1() 耗時=2ms
m2() 耗時=934ms
m3() 耗時=769ms
**/
方法名 | 功能說明 |
---|---|
static Class forName(String name) | 返回指定類名name的Class物件 |
object newlnstance() | 呼叫預設建構函式,返回該Class物件的一個範例 |
getName() | 返回此Class物件所表示的實體(類、介面、陣列類、基本型別等)名稱 |
Class [] getInterfaces() | 獲取當前Class物件的介面 |
ClassLoader getClassLoader() | 返回該類的類載入器 |
Class getSuperclass() | 返回表示此Class所表示的實體的超類的Class |
Constructor[] getConstructors() | 返回一個包含某些Constructor物件的陣列 |
Field[] getDeclaredFields() | 返回Field物件的一個陣列 |
Method getMethod(String name,Class…<?> paramTypes) | 返回一個Method物件,此物件的形參型別為paramType |
package com.jwt.reflection;
import java.lang.reflect.Field;
public class Class02 {
public static void main(String[] args) throws Exception {
String classAllPath = "com.jwt.reflection.Car";
//1 . 獲取到Car 類對應的Class 物件
Class<?> cls = Class.forName(classAllPath);//<?> 表示不確定的Java 型別
//2. 輸出cls
System.out.println(cls); //顯示cls 物件, 是哪個類的Class 物件
System.out.println(cls.getClass());//輸出cls 執行型別java.lang.Class
//3. 得到包名
System.out.println(cls.getPackage().getName());//包名
//4. 得到全類名
System.out.println(cls.getName());
//5. 通過cls 建立物件範例
Car car = (Car) cls.newInstance();
System.out.println(car);//car.toString()
//6. 通過反射獲取屬性brand
Field brand = cls.getField("brand");
System.out.println(brand.get(car));//寶馬
//7. 通過反射給屬性賦值
brand.set(car, "賓士");
System.out.println(brand.get(car));//賓士
//8. 得到所有的屬性(欄位)
System.out.println("=======所有的欄位屬性====");
Field[] fields = cls.getFields();
for (Field f : fields) {
System.out.println(f.getName());//名稱
}
}
}
class Car {
public String brand = "寶馬";
public int price = 500000;
public String color = "白色";
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
", color='" + color + '\'' +
'}';
}
}
/**
class com.jwt.reflection.Car
class java.lang.Class
com.jwt.reflection
com.jwt.reflection.Car
Car{brand='寶馬', price=500000, color='白色'}
寶馬
賓士
=======所有的欄位屬性====
brand
price
color
**/
1、Class.forName
前提:已知一個類的全名稱,且該類路徑下,可通過 Class 類的靜態方法 forName() 獲取,可能丟擲ClassNotFoundException 異常
範例:Class cls1 = Class.forName(「java.lang.Cat」);
應用場景:多用於組態檔,讀取類全路徑,載入類
2、類名.class
前提:若已知具體的類,通過類的 class 獲取,該方式最為安全可靠,程式效能最高
範例:Class cls2 = Car.class;
應用場景:多用於引數傳遞,比如通過反射得到對應構造器物件
3、物件.getClass()
前提:已知某個類的範例,呼叫該範例的 getClass() 方法獲取 Class 物件
範例:Class cls3 = 物件.getClass();//執行型別
應用場景:通過建立好的物件,獲取 Class 物件
4、通過類載入器
ClassLoader classLoader = 物件.getClass().getClassLoader();
Class cls4 = classLoader.loadClass(「類的全類名」);
5、基本資料(int,char,boolean,float,double,byte,long,short)按如下方式得到Class類物件
Class cls5 = 基本資料型別.class
6、基本資料型別對應的包裝類,可以通過 .TYPE 得到 Class 類物件
Class cls6 = 包裝類.TYPE
package com.jwt.reflection;
public class GetClass_ {
public static void main(String[] args) throws ClassNotFoundException {
//1. Class.forName
String classAllPath = "com.jwt.reflection.Car"; //通過讀取組態檔獲取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1);
//2. 類名.class , 應用場景: 用於引數傳遞
Class cls2 = Car.class;
System.out.println(cls2);
//3. 物件.getClass(), 應用場景,有物件範例
Car car = new Car();
Class cls3 = car.getClass();
System.out.println(cls3);
//4. 通過類載入器【4 種】來獲取到類的Class 物件
//(1)先得到類載入器car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通過類載入器得到Class 物件
Class cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4);
//5. 基本資料(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class 類物件
Class<Integer> cls5 = int.class;
System.out.println(cls5);//int
//6. 基本資料型別對應的包裝類,可以通過.TYPE 得到Class 類物件
Class<Integer> cls6 = Integer.TYPE;
System.out.println(cls6);
}
}
/**
class com.jwt.reflection.Car
class com.jwt.reflection.Car
class com.jwt.reflection.Car
class com.jwt.reflection.Car
int
int
**/
package com.jwt.reflection;
import java.io.Serializable;
public class AllTypeClass {
public static void main(String[] args) {
Class<String> aClass1 = String.class;//外部類
Class<Serializable> aClass2 = Serializable.class;//介面
Class<Integer[]> aClass3 = Integer[].class;//陣列
Class<Integer[][]> aClass4 = Integer[][].class;//二維陣列
Class<Deprecated> aClass5 = Deprecated.class;//註解
Class<Thread.State> aClass6 = Thread.State.class;//列舉
Class<Long> aClass7 = long.class;//基本資料型別
Class<Void> aClass8 = void.class;//void資料型別
Class<Class> aClass9 = Class.class;//Class類
System.out.println(aClass1);
System.out.println(aClass2);
System.out.println(aClass3);
System.out.println(aClass4);
System.out.println(aClass5);
System.out.println(aClass6);
System.out.println(aClass7);
System.out.println(aClass8);
System.out.println(aClass9);
}
}
反射機制是 Java 實現動態語言的關鍵,也就是通過反射實現類動態載入
Dog dog = new Dog();
Class cls = Class.forName("Person");
Object o = cls.newInstance();
Method method = cls.getMethod("hi");
method.invoke(o);
類載入各階段完成任務
JVM在改階段的主要目的是將位元組碼從不同的資料來源(可能是 class 檔案、也可能是 jar 包,甚至網路)轉化為二進位制位元組流載入到記憶體中,並生成一個代表該類的 java.lang.Class 物件
JVM 會在該階段對靜態變數,分配內容並初始化(對應資料型別的預設初始值,如0、0L、null、false等)。這些變數所使用的記憶體都將在方法區中進行分配
class A {
//分析類載入的連結階段-準備屬性是如何處理
//1. n1 是範例屬性, 不是靜態變數,因此在準備階段,是不會分配記憶體
//2. n2 是靜態變數,分配記憶體n2 預設初始化0 ,而不是20
//3. n3 是static final 是常數, 他和靜態變數不一樣, 因為一旦賦值就不變n3 = 30
public int n1 = 10;
public static int n2 = 20;
public static final int n3 = 30;
}
虛擬機器器將常數池內的符號參照替換為直接參照的過程。
到初始化階段,才真正開始執行類中定義的 Java 程式程式碼,此階段是執行
@Test
public void api_01() throws ClassNotFoundException, NoSuchMethodException {
//得到Class 物件
Class<?> personCls = Class.forName("com.jwt.reflection.Person");
//getName:獲取全類名
System.out.println(personCls.getName());//com.hspedu.reflection.Person
//getSimpleName:獲取簡單類名
System.out.println(personCls.getSimpleName());//Person
//getFields:獲取所有public 修飾的屬性,包含本類以及父類別的
Field[] fields = personCls.getFields();
for (Field field : fields) {//增強for
System.out.println("本類以及父類別的屬性=" + field.getName());
}
System.out.println("==========================");
//getDeclaredFields:獲取本類中所有屬性
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本類中所有屬性=" + declaredField.getName());
}
System.out.println("==========================");
//getMethods:獲取所有public 修飾的方法,包含本類以及父類別的
Method[] methods = personCls.getMethods();
for (Method method : methods) {
System.out.println("本類以及父類別的方法=" + method.getName());
}
System.out.println("==========================");
//getDeclaredMethods:獲取本類中所有方法
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本類中所有方法=" + declaredMethod.getName());
}
System.out.println("==========================");
//getConstructors: 獲取所有public 修飾的構造器,包含本類
Constructor<?>[] constructors = personCls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("本類的構造器=" + constructor.getName());
}
System.out.println("==========================");
//getDeclaredConstructors:獲取本類中所有構造器
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("本類中所有構造器=" + declaredConstructor.getName());//這裡老師只是輸出名
}
System.out.println("==========================");
//getPackage:以Package 形式返回包資訊
System.out.println(personCls.getPackage());//com.hspedu.reflection
//getSuperClass:以Class 形式返回父類別資訊
Class<?> superclass = personCls.getSuperclass();
System.out.println("父類別的class 物件=" + superclass);
System.out.println("==========================");
//getInterfaces:以Class[]形式返回介面資訊
Class<?>[] interfaces = personCls.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println("介面資訊=" + anInterface);
}
System.out.println("==========================");
//getAnnotations:以Annotation[] 形式返回註解資訊
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("註解資訊=" + annotation);//註解
}
}
/**
com.jwt.reflection.Person
Person
本類以及父類別的屬性=name
本類以及父類別的屬性=hobby
==========================
本類中所有屬性=name
本類中所有屬性=age
本類中所有屬性=job
本類中所有屬性=sal
==========================
本類以及父類別的方法=m1
本類以及父類別的方法=hi
本類以及父類別的方法=wait
本類以及父類別的方法=wait
本類以及父類別的方法=wait
本類以及父類別的方法=equals
本類以及父類別的方法=toString
本類以及父類別的方法=hashCode
本類以及父類別的方法=getClass
本類以及父類別的方法=notify
本類以及父類別的方法=notifyAll
==========================
本類中所有方法=m1
本類中所有方法=m2
本類中所有方法=m4
本類中所有方法=m3
==========================
本類的構造器=com.jwt.reflection.Person
本類的構造器=com.jwt.reflection.Person
==========================
本類中所有構造器=com.jwt.reflection.Person
本類中所有構造器=com.jwt.reflection.Person
本類中所有構造器=com.jwt.reflection.Person
==========================
package com.jwt.reflection
父類別的class 物件=class com.jwt.reflection.A
==========================
介面資訊=interface com.jwt.reflection.IA
介面資訊=interface com.jwt.reflection.IB
==========================
**/
測試程式碼
class A {
public String hobby;
public void hi() {}
public A() {}
public A(String name) {}
}
interface IA { }
interface IB { }
@Deprecated
class Person extends A implements IA, IB {
//屬性
public String name;
protected static int age; // 4 + 8 = 12
String job;
private double sal;
//構造器
public Person() {}
public Person(String name) {}
//私有的
private Person(String name, int age) {}
//方法
public void m1(String name, int age, double sal) {}
protected String m2() {
return null;
}
void m3() {}
private void m4() {}
}
@Test
public void api_02() throws ClassNotFoundException, NoSuchMethodException {
//得到Class 物件
Class<?> personCls = Class.forName("com.jwt.reflection.Person");
//java.lang.reflect.Field
//規定說明: 預設修飾符是0 , public 是1 ,private 是2 ,protected 是4 , static 是8 ,final 是16
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本類中所有屬性=" + declaredField.getName()
+ " 該屬性的修飾符值=" + declaredField.getModifiers()
+ " 該屬性的型別=" + declaredField.getType()
);
}
System.out.println("==========================");
//java.lang.reflect.Mehod
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本類中所有方法=" + declaredMethod.getName()
+ " 該方法的存取修飾符值=" + declaredMethod.getModifiers()
+ " 該方法返回型別" + declaredMethod.getReturnType()
);
}
for (Method declaredMethod : declaredMethods) {
//輸出當前這個方法的形引陣列情況
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("該方法的形參型別=" + parameterType);
}
}
System.out.println("==========================");
//java.lang.reflect.Constructor
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("本類中所有構造器=" + declaredConstructor.getName());//只是輸出名
}
for (Constructor<?> declaredConstructor : declaredConstructors) {
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("該構造器的形參型別=" + parameterType);
}
}
}
/**
本類中所有屬性=name 該屬性的修飾符值=1 該屬性的型別=class java.lang.String
本類中所有屬性=age 該屬性的修飾符值=12 該屬性的型別=int
本類中所有屬性=job 該屬性的修飾符值=0 該屬性的型別=class java.lang.String
本類中所有屬性=sal 該屬性的修飾符值=2 該屬性的型別=double
==========================
本類中所有方法=m1 該方法的存取修飾符值=1 該方法返回型別void
本類中所有方法=m2 該方法的存取修飾符值=4 該方法返回型別class java.lang.String
本類中所有方法=m4 該方法的存取修飾符值=2 該方法返回型別void
本類中所有方法=m3 該方法的存取修飾符值=0 該方法返回型別void
該方法的形參型別=class java.lang.String
該方法的形參型別=int
該方法的形參型別=double
==========================
本類中所有構造器=com.jwt.reflection.Person
本類中所有構造器=com.jwt.reflection.Person
本類中所有構造器=com.jwt.reflection.Person
該構造器的形參型別=class java.lang.String
該構造器的形參型別=int
該構造器的形參型別=class java.lang.String
**/
Class類相關方法
Constructor類相關方法
package com.jwt.reflection;
import java.lang.reflect.Constructor;
public class ReflecCreateInstance {
public static void main(String[] args) throws Exception {
//1. 先獲取到User 類的Class 物件
Class<?> userClass = Class.forName("com.jwt.reflection.User");
//2. 通過public 的無參構造器建立範例
Object user1 = userClass.newInstance();
System.out.println(user1);
//3. 通過public 的有參構造器建立範例
//3.1 先得到對應構造器
Constructor<?> constructor = userClass.getConstructor(String.class);
//3.2 建立範例,並傳入實參
Object user2 = constructor.newInstance("小簡");
System.out.println(user2);
//4. 通過非public 的有參構造器建立範例
//4.1 得到private 的構造器物件
Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
//4.2 建立範例
//暴破【暴力破解】, 使用反射可以存取private 構造器/方法/屬性
constructor1.setAccessible(true);
Object user3 = constructor1.newInstance(100, "張三丰");
System.out.println(user3);
}
}
class User {
private int age = 10;
private String name = "小明";
public User() {//無參public
}
public User(String name) {//public 的有參構造器
this.name = name;
}
private User(int age, String name) {//private 有參構造器
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}
Field f = class物件.getDeclaredField(屬性名);
f.setAccessible(true); //f是Field
f.set(o,值); //o表示物件
f.get(o); //o表示物件
package com.jwt.reflection;
import java.lang.reflect.Field;
public class ReflecAccessProperty {
public static void main(String[] args) throws Exception {
//1. 得到Student 類對應的Class 物件
Class<?> stuClass = Class.forName("com.jwt.reflection.Student");
//2. 建立物件
Object o = stuClass.newInstance();//o 的執行型別就是Student
System.out.println(o.getClass());//Student
System.out.println(o);
//3. 使用反射得到age 屬性物件
Field age = stuClass.getField("age");
System.out.println(age.get(o));//返回age 屬性的值
age.set(o, 88);//通過反射來操作屬性
System.out.println(o);
System.out.println(age.get(o));
//4. 使用反射操作name 屬性
Field name = stuClass.getDeclaredField("name");
//對name 進行暴破, 可以操作private 屬性
name.setAccessible(true);
name.set(o, "小明");
System.out.println(name.get(o)); //獲取屬性值
System.out.println(o);
name.set(null, "小紅");//因為name 是static屬性,因此o 也可以用null
System.out.println(name.get(null));//獲取屬性值, 要求name 是static
System.out.println(o);
}
}
class Student {//類
public int age;
private static String name;
public Student() {//構造器
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
Method m = class物件.getDeclaredMethod(方法名,XX.class);
Object o = class物件.newlnstance();
m.setAccessible(true);
Object returnValue = m.invoke(o,實參列表);
package com.jwt.reflection;
import java.lang.reflect.Method;
public class ReflecAccessMethod {
public static void main(String[] args) throws Exception {
//1. 得到Boss 類對應的Class 物件
Class<?> bossCls = Class.forName("com.jwt.reflection.Boss");
//2. 建立物件
Object o = bossCls.newInstance();
//3. 呼叫public 的hi 方法
//3.1 得到hi 方法物件
Method hi = bossCls.getMethod("hi", String.class);//OK
//Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK
//3.2 呼叫
hi.invoke(o, "小明");
//4. 呼叫private static 方法
//4.1 得到say 方法物件
Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
//4.2 因為say 方法是private, 所以需要暴破,原理和前面講的構造器和屬性一樣
say.setAccessible(true);
System.out.println(say.invoke(o, 100, "張三", '男'));
//4.3 因為say 方法是static 的,還可以這樣呼叫,可以傳入null
System.out.println(say.invoke(null, 200, "李四", '女'));
//5. 在反射中,如果方法有返回值,統一返回Object , 但是他執行型別和方法定義的返回型別一致
Object reVal = say.invoke(null, 300, "王五", '男');
System.out.println("reVal 的執行型別=" + reVal.getClass());//String
//在演示一個返回的案例
Method m1 = bossCls.getDeclaredMethod("m1");
Object reVal2 = m1.invoke(o);
System.out.println("reVal2 的執行型別=" + reVal2.getClass());//Monster
}
}
class Monster {}
class Boss {//類
public int age;
private static String name;
public Boss() {//構造器
}
public Monster m1() {
return new Monster();
}
private static String say(int n, String s, char c) {//靜態方法
return n + " " + s + " " + c;
}
public void hi(String s) {//普通public 方法
System.out.println("hi " + s);
}
}
通過反射修改私有成員變數
package com.jwt.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Homework01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
Class<?> aClass = Class.forName("com.jwt.reflection.PrivateTest");
Object o = aClass.newInstance();
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"小明");
Method getName = aClass.getMethod("getName");
Object returnValue = getName.invoke(o);
System.out.println("returnValue = " + returnValue);
}
}
class PrivateTest{
private String name = "hellokitty";
public String getName() {
return name;
}
}
利用反射和 File 完成以下功能
package com.jwt.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Homework02 {
public static void main(String[] args) throws Exception, {
//得到 File 類的 class 物件
Class<?> aClass = Class.forName("java.io.File");
//列印 File 類的所有構造器
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor<?> i:declaredConstructors){
System.out.println("File構造器 = " + i);
}
//指定構造器建立File物件
Constructor<?> dc = aClass.getDeclaredConstructor(String.class);
Object fileObj = dc.newInstance("/Users/jianjian/Downloads/mynew.txt");
//得到createNewFile的方法物件
Method createNewFile = aClass.getMethod("createNewFile");
createNewFile.invoke(fileObj);
System.out.println("建立成功");
}
}