JAVA反射例の詳細と紹介

7303 ワード

私たちはJava反射が重要だと知っていますが、今回はレンガを投げます!!!
一:反射
反射は実行状態において、いずれのクラスに対しても、このクラスのすべての属性と方法を知ることができる.いずれのオブジェクトに対しても、メソッドとプロパティを呼び出すことができます.
Javaの反射を使用するには、一般的に次の3つのステップがあります.
1:操作したいクラスのクラスオブジェクトを取得する
2:手順1で取得したClassオブジェクトから操作クラスを取得する方法または属性名
3:操作ステップ2で取得する方法または属性
二:例
Javaの反射メカニズムにはクラスにClass対応,クラスのメソッドにMethod対応があり,当然属性にもField対応がある.
2.1現在のクラスと親の関連プロパティを反射によって取得する
public class GetOtherClassFiled {  
    public static void main(String[] args) throws ClassNotFoundException {  
        Class> demo = Class.forName("com.tanjie.reflect.Persons");  
        System.out.println("          :=========================");  
        Field field[] = demo.getDeclaredFields();  
        for(int i=0;i type = field[i].getType();  
            System.out.println(prev + " " + type.getName() + " " + field[i].getName());  
        }  
        System.out.println("         :============================");  
        Field field2[] = demo.getFields();  
        for(int j=0;j type = field2[j].getType();  
            System.out.println(prev + " " + type.getName() + " " + field2[j].getName());  
        }  
     }  
  
} 

   
実行結果:
          :=========================  
private java.lang.String name  
         :============================  
public static final java.lang.String name

2.2クラスの関連属性、構築関数、インタフェースの取得
public class ClassImplesWhichInterface {  
      public static void main(String[] args) throws Exception {  
        Class> demo = Class.forName("com.tanjie.reflect.Persons");  
         //       
         Class> interfaces[] = demo.getInterfaces();  
        //      
         Class> parents = demo.getSuperclass();  
         //           
         Constructor> constructors[] = demo.getConstructors();  
         for (int i = 0; i < interfaces.length; i++) {  
             System.out.println("        :" + interfaces[i].getName());  
         }  
         for (int i = 0; i < constructors.length; i++) {  
             System.out.println("        :" + constructors[i]);  
         }  
         System.out.println("     :" + parents.getName());  
         for (int i = 0; i < constructors.length; i++) {  
           Class> paramenter[] = constructors[i].getParameterTypes();  
           int mo = constructors[i].getModifiers();  
           System.out.println(Modifier.toString(mo) + " " + constructors[i].getName());  
           for(int j=0;j

実行結果:
        :com.tanjie.reflect.Parents  
        :public com.tanjie.reflect.Persons()  
        :public com.tanjie.reflect.Persons(java.lang.String)  
     :java.lang.Object  
public com.tanjie.reflect.Persons  
public com.tanjie.reflect.Persons  
java.lang.String

三:実際の応用
上の2つの列は反射の一般的な方法を熟知しており、覚えられないときはapiをひっくり返すと使用され、反射に対応する方法が簡単明瞭になります.次に、プロジェクトで反射を利用する具体的な例を見てみましょう.
もし私たちがこのような需要があれば、あなたのプログラムの中で、よくいくつかのエラーコードを定義する列挙クラスがあって、エラーコードはどのように繰り返し定義されないことを保証することができますか?もし定義するたびに手動でチェックするのはきっと面倒で、私たちは反射を利用して動的なエラーコード検出を実現することができます.
3.1注釈クラスの定義
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.TYPE)  
public @interface EnumTag {  
  String name();  
}  

RetentionPolicy.RUNTIME:ソースコード、コンパイル後の.classはすべて情報を保存し、実行時にもこれらの情報をJVMにロードします.@Target内のElementTypeは、Annotationを作成するために使用できるタイプです.
3.2列挙クラスの定義
@EnumTag(name = "errorEnum")  
public enum ErrorEnum {  
      
    JAVA_TIME_OUT(1000),  
      
    ZOOKEEPER_TIME_OUT(2000);  
  
    private final int errorCode;  
  
    private final String errMessage;  
  
    /** 
     *        ,    
     *  
     * @param errorCode 
     *            errorCode 
     */  
    private ErrorEnum(int errorCode) {  
        this.errorCode = errorCode;  
        this.errMessage = "System Error";  
    }  
  
    public int getErrorCode() {  
        return errorCode;  
    }  
  
    public String getErrMessage() {  
        return errMessage;  
    }  
  
    public static List getErrorCodes() {  
        List errorCodeList = new ArrayList();  
        for (final ErrorEnum em : ErrorEnum.values()) {  
            int code = em.getErrorCode();  
            errorCodeList.add(code);  
        }  
        return errorCodeList;  
    }  
}  

  
3.3 beanの定義
public class ValidateEnumMark implements InitializingBean {  
  
    private List errorList;  
  
    public ValidateEnumMark() {  
        errorList = new ArrayList();  
    }  
  
    /** 
     *  
     *             @PostConstruct  @PreDestroy          bean        
     *  
     * @throws SecurityException 
     * @throws NoSuchMethodException 
     * @throws InvocationTargetException 
     * @throws IllegalArgumentException 
     * @throws IllegalAccessException 
     * 
     */  
    @SuppressWarnings("unchecked")  
    @PostConstruct  
    public void validate() throws NoSuchMethodException, SecurityException,  
            IllegalAccessException, IllegalArgumentException,  
            InvocationTargetException {  
        Reflections reflections = new Reflections(  
                "com.tanjie.reflect.application");  
        Set> sets = reflections.getTypesAnnotatedWith(EnumTag.class);  
        for (Class> demo : sets) {  
            //             
            Method method = demo.getDeclaredMethod("getErrorCodes",  
                    new Class[] {});  
            //               
            List list = (List) method.invoke(demo,  
                    new Object[] {});  
            if (null != list && !list.isEmpty()) {  
                for (Integer integer : list) {  
                    if (errorList.contains(integer)) {  
                        System.out.println("      ");  
                    } else {  
                        errorList.add(integer);  
                    }  
                }  
            }  
        }  
                System.out.println("            :" + errorList);  
    }  
  
    @Override  
    public void afterPropertiesSet() throws Exception {  
        System.out.println("    .....");  
    }  
}

   
スプリングのプロファイルに

  
  

上記の構成が完了すると、springコンテナが起動すると、まずプログラム全体に重複定義のエラーコードがあるかどうかを検出します.
4:反射のパフォーマンス
反射があまりよくないところが性能です.反射によってフィールドを取得したり、javaコードを直接使用するよりも方法が遅いからです.しかし、反射がどこに使われているかを見なければなりません.大きなプロジェクトでは、反射が重要ではなく、性能に影響を与えないところにしか使われていない場合、この性能の損失は重要ではありません.