JAvaメモ---反射メカニズム(1)

6942 ワード

引用する
  javaの反射メカニズムを覚えやすいように、ここで詳しくまとめてみました.主に後で忘れることを恐れて、このようにも思い出しやすいです.最近、余暇を利用してspringとMybatisのフレームワークを深く理解しているため、springのコアモジュールIOCの下部で実現される原理は反射メカニズムであり、mybatisもjavaの反射メカニズムを利用してオブジェクトの値を取得し、設定する.このことからjava反射メカニズムは強いように見えますが、実は面白いです.
Java言語では、クラス・ローダによってクラス・ファイルがロードされた後、JVMにClass構造を記述するメタ情報オブジェクトがプログラム化された方法で間接的に操作されます.このメタ情報オブジェクトによってClassの構造情報、構造関数、属性、メソッドなどを知ることができます.Javaは、ユーザがこのClassに関するメタ情報オブジェクトからClassオブジェクトを間接的に呼び出す機能を許可する.
反射の定義:
 JAVA反射機構は運転状態において、いずれのクラスについても、このクラスのすべての属性と方法を知ることができる.いずれのオブジェクトに対しても、そのメソッドとプロパティを呼び出すことができます.このような動的に取得された情報および動的にオブジェクトを呼び出す方法の機能をjava言語の反射メカニズムと呼ぶ.注意は運転状態です.
「プログラム実行時に、動的言語と呼ばれるプログラム構造または変数タイプを変更できます」.Javaは動的言語ではありません.しかし、Javaには非常に際立った動的相関メカニズムがあります.Reflectionは、Javaで実行時にコンパイル中に完全に未知のclassesをロードし、検出し、使用することができます.すなわち、Javaプログラムは、実行時に名前を知るclassをロードし、その完全な構造(methods定義を含まない)を知り、オブジェクトエンティティを生成したり、fieldsに値を設定したり、methodsを呼び出したりすることができます.
反射の理解
定義を見て少し分かりましたが、反射には「逆」の概念が含まれており、反射を解釈するにはまず「正」から解釈しなければなりません.一般的には、インスタンス化されたオブジェクトを生成するには必ずクラスがあります.次のようになります.
import java.util.Date;//    
public class ReflectionDemo {
    public static void main(String[] args) {     
        Date date = new Date();//           
        System.out.println(date);    
    }
}

「逆」とは、オブジェクトを通じてクラスを見つけることです.Objectクラスには次の方法があります.
public final Class getClass()

getClassメソッドでは、このオブジェクトに対応する反射クラス注を取得できます.反射のすべての汎用型は?と定義されています.戻り値はすべてObjectです.
import java.util.Date;//    
public class ReflectionDemo {
    public static void main(String[] args) {     
        Date date = new Date();//     
        Class> c =date.getClass();
        System.out.println(c);
    }
}
   :class java.util.Date 

getClass()を呼び出すと、クラスの完全な名前が得られることがわかりました.相手の出所を見つけた
Classクラスオブジェクトのインスタンス化
 java.lang.Classは、一般クラスと同様にObjecから継承されるクラスです.このクラスは反射操作の源であり、つまりすべての反射はこのようなものから行われ、どのようにして1つのオブジェクトに対応する反射クラスClassを取得するか、Javaでは3つの方法で1つのオブジェクトの反射クラスを取得することができます.
1.Objectクラスを呼び出すgetClass()メソッド(少ない)
すなわち、上記の例については、ここで省略する.
2.Classクラスが提供する静的メソッドforNameを呼び出します.
//import java.util.Date;//    
public class ReflectionDemo {
    public static void main(String[] args) throws Exception  {     
        Class> c = Class.forName("java.util.Date");
        System.out.println(c);
    }
}
  :class java.util.Date

注意:この場合、import文を使用して明確なクラスをインポートする必要はありません.クラス名は文字列で記述されます.
3.「クラス.class」で取得:
import java.util.Date;//    
public class ReflectionDemo {
    public static void main(String[] args){     
        Class> c = Date.class;
        System.out.println(c);
    }
}

実体化オブジェクトの反射(Reflection Materialized Objects)
一般的に、オブジェクトのインスタンス化操作は、構築方法とキーワードnewによって完了する必要があります.しかしクラスオブジェクトがあれば,反射を利用してオブジェクトのインスタンス化を実現できる.
Class> c = Class.forName("com.putao.Person");
    Person p = (Person)c.newInstance();//     new           
    p.setName("  ");
    System.out.println(p.getName());
  :  

  注意:newInstanceはデフォルトの無パラメトリック構築メソッドのみを呼び出すことができ、クラスに無パラメトリック構築メソッドが提供されていない場合は、有パラメトリック構築メソッドのみを明確に呼び出すことができます.(一般的にクラスを作成するときはできるだけパラメトリック構造を残す)Classクラスには構造を取得する方法があります
public Constructor getConstructor(Class... parameterTypes)


Class> c = Class.forName("com.putao.Person");
//      Person p = (Person)c.newInstance();
//      p.setName("  ");
    Constructor> con = c.getConstructor(String.class,int.class);
    Object obj = con.newInstance("  ",22);//     
    Person p2 = (Person) obj;
    System.out.println(p2.toString());
  :Person [name=  , age=22]

工場モデルの実現
ジルコニウムプログラムの開発は結合をできるだけ低減する.結合を低減する最善の方法はインタフェースを使用することであるが,インタフェースを使用してもキーワードnewから逃れられないため,実際にはnewが結合の鍵となる要素である.反射メカニズムでオブジェクトをインスタンス化する場合は、実際には「パッケージ.クラス」だけでよい
    package com.putao;
    interface Fruit{
        public void eat();
    }
     
    class Apple implements Fruit{
        @Override
        public void eat(){
            System.out.println("eat apple");
        }
    }
    class Grape implements Fruit{
        @Override
        public void eat(){
            System.out.println("eat grape");
        }
    }
    class Orange implements Fruit{
        @Override
        public void eat(){
            System.out.println("eat orange");
        }
    }
     
    class Factory{
        public static Fruit getInstance(String className){
            /*if("apple".equals(className)){
                return new Apple();
            }else if("orange".equals(className)){
                return new Orange();
            }
            return null;*/
            Fruit f = null;
            try {
                f = (Fruit)Class.forName(className).newInstance();
     
            } catch (Exception e) {
                e.printStackTrace();
            }
            return f;
     
        }
    }
     
    public class FactoryDemo{
        public static void main(String[] args){
            /*Fruit f = Factory.getInstance("apple");
            f.eat();
     
            Fruit f1 = Factory.getInstance("orange");
            f1.eat();*/
     
            Fruit f1= Factory.getInstance("com.putao.Apple");
            f1.eat();
     
            Fruit f2 = Factory.getInstance("com.putao.Orange");
            f2.eat();
            Fruit f3 = Factory.getInstance("com.putao.Grape");
            f3.eat();
     
        }
    }
      :eat apple
    eat orange
    eat grape

その後、インタフェースのサブクラスが追加されても、ファクトリクラスはオブジェクトのインスタンス化操作を完了することができ、このようなファクトリクラスは、すべての変化に対応することができる.これにより,結合を理解する目的が達成され,拡張性が非常に強い.
呼び出し方法、メンバーの反射
クラスには
           :
public Method[] getMethods() throws SecurityException
      :
public Method getMethod(String name, Class>... parameterTypes) throws
NoSuchMethodException, SecurityException
      :
public Field[] getDeclaredFields() throws SecurityException
      :
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException

例:取得方法
Class> c = Class.forName("com.putao.Person");
    Object obj =c.newInstance();
    Method setMet = c.getMethod("setName", String.class);
    setMet.invoke(obj, "  ");//     person  setName("  ")
    Method getMet = c.getMethod("getName");
    System.out.println(getMet.invoke(obj));//     person  getName()  
      :  

例:属性の取得
Class> c = Class.forName("com.putao.Person");
    Object obj =c.newInstance();    
    Field titleField = c.getDeclaredField("name");
    titleField.setAccessible(true);//    
    titleField.set(obj, "  ");//   Person   .name = "  "
    System.out.println(titleField.get(obj));//   Person   。name

転載先:https://www.cnblogs.com/favour/p/7282889.html