Javaのリフレクション機構

伊谢尔伦
リリース: 2016-11-30 09:47:01
オリジナル
1312 人が閲覧しました

Java のリフレクション メカニズムは Java の特徴の 1 つであり、リフレクション メカニズムを使用すると、プログラムをより柔軟にし、コード内のプログラムのハードコーディングを回避できます。 Java の基礎しか学んでいない多くの初心者と比較すると、リフレクションはまだ非常に曖昧で難しい概念です。リフレクションの応用例についていくつか説明します。

Javaのリフレクション機構とは、動的に情報を取得し、実行状態でオブジェクトのメソッドを動的に呼び出す機能を指します。 Java リフレクションには 3 つの動的プロパティがあります。1. 実行時のオブジェクト インスタンスの生成、2. 実行時の呼び出しと発行、3. 実行時の属性の変更。

それでは、反省の原理とは何でしょうか?次に、まず Java プログラムの実行プロセスを確認する必要があります。Java プログラムを実行するには、Java 仮想マシンによって Java クラスがロードされる必要があります。プログラムを実行する場合、必要なクラスはコンパイル中にすでにロードされています。ここで言及しなければなりませんが、コンパイル時とは何か、コンパイル時とは、コンパイラがコードをデバイスが認識できるコードに変換するときのこと、つまり、コンパイル時とは何かという明確な概念を持っていないと思います。たとえば、コンパイル コンパイラーは、構文にエラーがあるかどうか、キーワードや名前の記述にエラーがあるかどうかをチェックする、クラスをロードするなど、コンパイル中にいくつかの簡単な作業を実行します。これらはすべて、コンパイル中に行う必要があることです。ですが、実行時は何をするのでしょうか?ランタイムとは、プログラムがメモリにロードされた後、メモリ内で操作と判断を実行することです。

 int[] nums = new int[3];
        nums[4] = 12;
ログイン後にコピー

明らかに、上記のコードはエラーを引き起こします。配列添字の範囲外エラーが発生しましたが、プログラムはコンパイル時にエラーを報告しませんが、実行時に ArrayIndexOutOfBoundsException エラーを報告します。これがコンパイル時と実行時の違いです。

Java のリフレクション メカニズムは、コンパイル時にどのクラスがロードされるかはわかりません。プログラムの実行時にロードされて使用されます。簡単な図を使用して、リフレクションの実行プロセスを見てみましょう。

Javaのリフレクション機構

Java のリフレクション メカニズム。 Java クラスの構造を検出するこの機能は、「自己検査」になります。Eclipse などのソフトウェアを使用してコードを記述するときの自動プロンプト機能は、Java リフレクションの原理を使用します。では、Java のリフレクションを通じてどのような機能を実現できるのでしょうか? 1. 実行時に任意のオブジェクトが属するクラスを決定します。 2. 実行時に任意のクラスのオブジェクトを構築します。 3. 実行時に任意のクラスのプロパティとメソッドを決定します。 4. 実行時に任意のオブジェクトのメソッドを呼び出します。 Java リフレクションでよく使用されるクラスには、リフレクションのコア クラスである Class クラスが含まれます。Class クラスを通じて、クラスの属性、メソッドなどを取得できます。 Filed class: クラスの属性を表し、クラス内の属性の値を取得および設定できます。メソッド クラス: クラスのメソッドを表し、クラス内のメソッドに関する情報を取得したり、メソッドを実行したりするために使用できます。コンストラクター クラス: クラスのコンストラクター メソッドを表します。

さて、Java リフレクションに関する基本的な情報を学習しました。次に、コードを使用してリフレクションの各関数を 1 つずつ実装します。

最初の関数も最も単純なものです。まず、Class クラスを使用する必要があります。まずインスタンス化しますが、Class クラスにはコンストラクターがないので、どうやってインスタンス化しますか? Class クラスを作成するには 3 つの方法があります:

public static void main(String[] args) { //第一种方法,通过对象.getClass()方法 User user = new User();
        Class<? extends User> cs = user.getClass();
        System.out.println(cs); //第二种方法,通过类名.class Class<User> cs1 = User.class;
        System.out.println(cs1); //第三种方法,通过Class本身的forName()方法,注意forName()方法会抛出一样,并且里面的参数需要完整的包名和类名 Class<?> cs2 = null; try {
            cs2 = Class.forName("cn.fanfu.demo.User");
        } catch (ClassNotFoundException e) { // TODO Auto-generated catch block  e.printStackTrace();
        }
        System.out.println(cs2);
    }
ログイン後にコピー

3 番目の forName() メソッドは、クラスが不確かな場合にインスタンス化できます。柔軟性。

2 つ目は、Class クラスのパラメーター化された構築を通じて、Class クラス オブジェクトの新しいインスタンスを作成することです:

public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, 
InstantiationException, IllegalAccessException, InvocationTargetException { 
//在这里为了更直观的展示,直接使用String类 Class<?> cs =Class.forName("java.lang.String"); char[] ch = {&#39;大&#39;,&#39;家&#39;,&#39;好&#39;,&#39;!&#39;,&#39;!&#39;}; 
//调用Class类的有参构造函数,函数里的值为类.class Constructor<?> cst = cs.getConstructor(char[].class);
       String name = (String) cst.newInstance(ch);
       System.out.println(name); //因为这里的异常会使代码没有直观的显示,所以我直接抛给虚拟机 }
ログイン後にコピー

3 つ目は、クラスの構造、インターフェイス、メソッド、プロパティなどの一連の要素を取得することです。 :

public static void main(String[] args) throws ClassNotFoundException,
            SecurityException, NoSuchMethodException, IllegalArgumentException,
            InstantiationException, IllegalAccessException,
            InvocationTargetException { //先创建好两个对象 Class<?> cs = Class.forName("cn.fanfu.demo.User");
        Constructor<?>[] con = null; //通过getConstructors()方法返回一个Constructor[]数组,数组里存储的是该类的各个构造 con = cs.getConstructors(); for (Constructor<?> item : con) {
            System.out.println(item);
        } //通过getInterfaces()方法返回一个Class<?>[]数组,数组里存储的是该类的各个接口 Class<?>[] inter = cs.getInterfaces(); for (Class<?> item : inter) {
            System.out.println(item);
        } //通过getSuperclass()方法返回一个Class<?> Class<?> parent = cs.getSuperclass(); //java中只支持单继承,所以只有一个父类  System.out.println(parent); //通过getMethods()方法返回一个Method[]数组,数组里存储的是该类的各个方法 Method[] method = cs.getMethods(); for (Method item : method) {
            System.out.println(item);
        } //通过getDeclaredFields()方法返回一个Field[]数组,数组里存储的是该类的各个属性 Field[] fiel = cs.getDeclaredFields(); for (Field item : fiel) {
            System.out.println(item);
        } //getDeclaredFields()方法可以获取全部属性,getFields()方法只能获取到公有属性 Field[] fiel1 = cs.getFields(); for (Field item : fiel1) {
            System.out.println(item);
        }
    }
ログイン後にコピー

4 番目は、クラスの属性の値を取得または変更します:

public static void main(String[] args) throws ClassNotFoundException,
            SecurityException, NoSuchMethodException, IllegalArgumentException,
            InstantiationException, IllegalAccessException,
            InvocationTargetException, NoSuchFieldException { //创建User对象 User us = new User();
        us.setAge(12);
        us.setName("张三");
        Class<?> cs = us.getClass(); //获取私有属性的值 Field fl = cs.getDeclaredField("name"); //要先设置允许访问 fl.setAccessible(true); //通过get方法指定对象获取值 String name = (String) fl.get(us);
        System.out.println(name); //通过set方法指定对象并修改值 fl.set(us, "李四");
        String name2 = (String) fl.get(us);
        System.out.println(name2);        
    }
ログイン後にコピー

5 番目は、リフレクションを通じてメソッドを呼び出します:

public static void main(String[] args) throws ClassNotFoundException,
            SecurityException, NoSuchMethodException, IllegalArgumentException,
            InstantiationException, IllegalAccessException,
            InvocationTargetException, NoSuchFieldException { //创建User对象 User us = new User();
        us.setAge(12);
        us.setName("张三");
        Class<?> cs = us.getClass(); //通过getMethod()方法获取类中方法,该方法有两个参数,一个指定方法名,一个指定方法中参数的类型 Method mm = cs.getMethod("say"); //通过invoke()方法调用方法,该方法有两个参数,一个指定对象,另一个传递参数  mm.invoke(us);
    }
ログイン後にコピー


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート