オブジェクト実行メソッドを動的に作成する
クラスのオブジェクトを作成し、ClassオブジェクトのNewInstance()メソッドを呼び出します
- クラスにはパラメーターのないコンストラクターが必要です
- クラスのコンストラクタのアクセス権は十分である必要があります
指定されたメソッドを呼び出す
リフレクションを介して、クラス内のメソッドを呼び出し、メソッドクラスを介して完了します。
- ClassクラスのgetMethod(String name、Class ... parameterTypes)メソッドを使用してMethodオブジェクトを取得し、このメソッドの操作に必要なパラメータータイプを設定します。
- 次に、Object invoke(Object obj、Object [] args)を使用して、メソッドに設定するobjオブジェクトのパラメーター情報を呼び出して渡します。
オブジェクト呼び出し(Object obj、Object…args)
- オブジェクトは元のメソッドの戻り値に対応します。元のメソッドに戻り値がない場合、この時点でnullを返します。
- 元のメソッドが静的メソッドの場合、仮パラメーターObjectobjはnullになる可能性があります
- 元のメソッドパラメータリストが空の場合、Object [] argsはnullです
- 元のメソッドがプライベートの場合、このinvoke()メソッドを呼び出してプライベートメソッドにアクセスする前に、メソッドオブジェクトのsetAccessible(true)メソッドを明示的に呼び出す必要があります。
package Reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//动态创建对象,通过反射
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得Class对象
Class c1 = Class.forName("Reflection.User");
//构造一个对象
// User user = (User)c1.newInstance(); //本质是调用了类的无参构造器
// System.out.println(user);
//通过构造器创建对象
Constructor con = c1.getDeclaredConstructor( int.class,String.class, int.class);
User user11 = (User) con.newInstance(001, "XXX", 18);
System.out.println(user11);
//通过反射调用普通方法
User u = (User)c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke :激活的意思
//(对象,"方法值")
setName.invoke(u,"XXXXX");
System.out.println(u.getName());
//通过反射操作属性
System.out.println("------------------------------");
User u21=(User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,我们需要关闭程序权限的安全检测
name.setAccessible(true);
name.set(u21,"AAAAA");
System.out.println(u21.getName());
}
}
setAccessible
- メソッドおよびフィールドコンストラクタオブジェクトには、SetAccessible()メソッドがあります
- setAccessibleが有効な場合に、アクセスセキュリティチェックを有効または無効に切り替えます
- パラメータ値はtrueであり、反映されたオブジェクトが使用中にJava言語アクセスチェックをキャンセルする必要があることを示します
- 反射の効率を向上させます。コードでリフレクションを使用する必要があり、コードを頻繁に呼び出す必要がある場合は、Trueに設定してください
- 他の方法ではアクセスできないプライベートメンバーにもアクセスできるようにする
- パラメータ値はFalseであり、リフレクションオブジェクトがJava言語アクセスチェックを実装する必要があることを示します
ケース共通法反射モードと反射モード閉検出比較速度
package Reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test09 {
//普通方法
public static void test1(){
User u=new User();
long startTime=System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
u.getName();
}
long entTime=System.currentTimeMillis();
System.out.println("时间为:"+(entTime-startTime)+"ms");
}
//反射方式调用
public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User u=new User();
Class c1 = u.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
long startTime=System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(u,null);
}
long entTime=System.currentTimeMillis();
System.out.println("时间为:"+(entTime-startTime)+"ms");
}
//反射方式调用 关闭检测
public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User u=new User();
Class c1 = u.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true);
long startTime=System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(u,null);
}
long entTime=System.currentTimeMillis();
System.out.println("时间为:"+(entTime-startTime)+"ms");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test1(); //10ms
test2(); //4083ms
test3(); //1649ms
}
}