まず、反射は何ですか?
Javaリフレクション機構は、任意のクラスのために、それらは、このクラスのすべてのプロパティとメソッドに知らされており、動作状態にある、任意のオブジェクトについて、そのメソッドとプロパティを呼び出すことが可能であり、得られたこの動的および動的情報関数呼び出しは、オブジェクトのメソッドは、反射Java言語と呼ばれています。
第二に、あなたは何をするリフレクションを使用することができますか?
私たちは、プログラムが実行時に任意の既知のクラス名に関する情報を取得することを可能にするコンストラクタ(コンストラクタ)、フィールド(属性)、メソッド(方法)などを含む含む、および実行時のフィールドの内容を変更することができ、内部反射機構ということを知っていますまたはメソッドを呼び出します。動的プロキシなどの実現がある;次に、我々は、コードを書くことがより柔軟であることができる、コードは、コードの結合を低減、コンポーネント間のソースコードへのリンクを必要とせずに、実行時に組み立てることができるが、なお、反射の不適切な使用これは、資源の大量消費になります!
第三に、の事前知識
(A)クラスをロードします
リフレクションを使用する方法を知りたい、我々は最初のロードのタイプを理解する必要があります。
あなたはクラスがまだメモリにロードされていない場合、接続、負荷によって、システムのクラスを使用する場合は、クラスを初期化するための3つのステップを初期化します。
- 負荷
クラスファイルを参照するクラスのオブジェクトを作成するためのメモリ、そして誰に読み込まれます。
システムは、Classオブジェクトを構築する際に使用されている任意のクラス。 - 接続
正しい内部構造ことを確認し、そして協調及び他のタイプの
割り当てられたメモリの静的メンバクラスを担当する準備ができ、デフォルトの初期値設定
シンボル解像度バイナリデータ型が直接参照内の参照を置換します - 初期化ステップの基本的な初期化
(ⅱ)クラスローダ
-
クラスローダ:のために固有のロードを担当するの.classファイル、および対応するClassオブジェクトを生成します。
私たちは、クラスローディング機構を気に、しかし、このメカニズムを理解していないが、我々はプログラムの理解を実行することができます。 -
作曲クラスローダ
ブートストラップクラスローダのルートクラスローダ
拡張クラスローダ拡張クラスローダー
Sysetmクラスローダシステムクラスローダ -
クラスローダ作用
も、ブートストラップ・クラス・ローダとして知られている(1)ブートストラップクラスローダのルートクラスローダを、。Javaのコアクラスのロードを担当する
ようなシステム、文字列などなどを。JDK、JREのlibディレクトリの下にrt.jarのファイルで(2)拡張クラスローダ拡張クラスローダ。ジャーにJRE拡張ディレクトリをロードするための責任。
ディレクトリEXT下のJRE JDK libディレクトリに
(3)Sysetmクラスローダシステムクラスローダ。javaコマンドからクラスファイルをロードするための責任、およびCLASSPATH環境変数に指定のjarパッケージおよびクラスパス時にJVMの起動
第四には、どのようにリフレクションを使用するには?
Personクラスを既存の
public class Person {
private String name;
int age;
public String address;
public Person() {
}
private Person(String name) {
this.name = name;
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public void show() {
System.out.println("show");
}
public void method(String s) {
System.out.println("method " + s);
}
public String getString(String s, int i) {
return s + "-->" + i;
}
private void function() {
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
だから、このクラスのために、どのようにそれの反射を使用するには?
(A)、メモリ内のクラスのバイトコードファイルに対応するClassオブジェクトを取得します。
/**
*有三种方式可以获得Class对象
*/
//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
// 类型的对象,而我不知道你具体是什么类,用这种方法
Person p1 = new Person();
Class c1 = p1.getClass();
//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
// 这说明任何一个类都有一个隐含的静态成员变量 class
Class c2 = Person.class;
//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
// 但可能抛出 ClassNotFoundException 异常
Class c3 = Class.forName("com.ys.reflex.Person");
注:JVM内のクラスのみ、我々はC3が==比較して、C1、C2の上に取得することを、クラスのインスタンスが存在します、結果は真であります
(B)クラスクラスのメソッドによって提供されるコンストラクタを得ます
- 工法を取得
/**
*反射之获取无参构造方法,并使用
*/
public class TestConstructor01 {
public static void main(String[] args) throws Exception {
//获取Class对象
Class c = Class.forName("study01.Person");
//获取无参构造函数
Constructor con = c.getDeclaredConstructor();
//创建实例
Object obj = con.newInstance();
}
}
/**
*反射之获取带参构造方法,并使用
*/
public class TestConstructor02 {
public static void main(String[] args) throws Exception {
//获取Class对象
Class c = Class.forName("study01.Person");
//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
//获取构造方法
Constructor con = c.getDeclaredConstructor(String.class, int.class, String.class);
//创建实例
Object obj = con.newInstance("张三", 27, "北京");
}
}
/**
*反射之获取private修饰的构造方法,并使用
*/
public class TestConstructor03 {
public static void main(String[] args) throws Exception{
//获取Class对象
Class c = Class.forName("study01.Person");
//获取构造方法
Constructor con = c.getDeclaredConstructor(String.class);
//设置访问权限
con.setAccessible(true); //值为true则指示反射的对象在使用时应该取消Java语言访问检查。
//创建实例
Object obj = con.newInstance("林青霞");
}
}
(C)操作部材可変クラスのクラスによって提供される方法
- メンバ変数の割り当てへ
public class TestField01 {
public static void main(String[] args) throws Exception{
test();
}
public static void test() throws Exception {
//获取Class对象
Class c = Class.forName("study01.Person");
//获取Constructor
Constructor con = c.getDeclaredConstructor();
//创建实例
Object obj = con.newInstance();
System.out.println(obj);
//获取Field
Field addressField = c.getDeclaredField("address");
//赋值Field
addressField.setAccessible(true);
addressField.set(obj, "北京");
System.out.println(obj);
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj, "张三");
System.out.println(obj);
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj, 27);
System.out.println(obj);
}
}
次のようにテスト結果は以下のとおりです。
- メンバ変数の取得
public class TestField02 {
public static void main(String[] args) throws Exception{
test();
}
public static void test() throws Exception {
//获取Class对象
Class c = Class.forName("study01.Person");
//获取Constructor
Constructor con = c.getDeclaredConstructor();
//创建实例
Object obj = con.newInstance();
System.out.println(obj);
//获取Field
Field addressField = c.getDeclaredField("address");
//赋值Field
addressField.setAccessible(true);
addressField.set(obj, "北京");
System.out.println(obj);
System.out.println(addressField.get(obj));
}
}
次のようにテスト結果は以下のとおりです。
(IV)法による方法は、クラスのクラスのメンバーが提供するコール
/**
* 反射之获取无参无返回值成员方法,并调用
*/
public class TestMethod01 {
public static void main(String[] args) throws Exception {
test0();
}
//获取单个方法对象
/**
* 1、public 方法 getMethod(String name, Class<?>... parameterTypes):获取所有方法,包括父类的
* 参数 : name:方法的名称 parameterTypes:该方法的参数列表
* 2、public 方法 getDeclaredMethod(String name, Class<?>... parameterTypes):获取所有子类定义的方法
* 参数 : name:方法的名称 parameterTypes:该方法的参数列表
*/
public static void test() throws Exception {
//获取Class对象
Class c = Class.forName("study01.Person");
//获取构造方法
Constructor con = c.getDeclaredConstructor();
//创建实例
Object obj = con.newInstance();
//获取需要的方法对象
Method m = c.getDeclaredMethod("show");
//调用方法
/**
* public Object invoke(Object obj, Object... args)
* obj - 被调用的对象 args - 用于方法调用的参数
*/
m.invoke(obj);
}
}
次のようにテスト結果は以下のとおりです。
/**
* 反射之获取有参有返回值成员方法,并调用
*/
public class TestMethod02 {
public static void main(String[] args) throws Exception {
//获取Class对象
Class c = Class.forName("study01.Person");
//获取构造方法
Constructor con = c.getDeclaredConstructor();
//创建实例
Object obj = con.newInstance();
//获取需要的方法对象
//public void method(String s)
Method m = c.getDeclaredMethod("method", String.class);
m.invoke(obj, "java");
//public String getString(String s, int i)
Method m1 = c.getDeclaredMethod("getString", String.class, int.class);
Object rst = m1.invoke(obj, "hello", 200);
System.out.println(rst);
}
}
次のようにテスト結果は以下のとおりです。
/**
* 反射之获取privste成员方法,并调用
*/
public class TestMethod02 {
public static void main(String[] args) throws Exception {
//获取Class对象
Class c = Class.forName("study01.Person");
//获取构造方法
Constructor con = c.getDeclaredConstructor();
//创建实例
Object obj = con.newInstance();
//获取需要的方法对象
//private void function()
Method m2 = c.getDeclaredMethod("function");
m2.setAccessible(true);
m2.invoke(obj);
}
}
次のようにテスト結果は以下のとおりです。
V.の概要
反射の柔軟な使用は、より柔軟なコードに私たちを許可しますが、すべては等の複雑さを増大し、システムの消費を反映し、双方の性能を有し、本当に公正使用です!