リフレクション、Java の基本入門

巴扎黑
リリース: 2017-07-20 13:09:48
オリジナル
1131 人が閲覧しました

今日はJavaの基本で反射防止について学びました。勉強した後の私の個人的な理解によれば、リフレクションはクラス、属性、メソッドなどを取得するためのツールのセットです。 (実際、内省を学んだ後は、喉の渇きを潤すために冷たい水を飲んでいるような感じがします。でも、その味はよくわかりません。本質を学んでいないのかもしれません。何かが足りないと感じます。これこれは Java に基づいて学んだことの最後の部分です。もう一度復習してから、JVM やコンピュータ システムに関する本を読む時間も欲しいと思っています。私は専門家であり、思考にいくつかの欠陥があります。)

リフレクションを学ぶ前に、最初に変数パラメーターを思い出しました。

public static void main(String[] args) {
            test();//调用方法1test("JAVA");//调用方法2test("JAVA","工程师");//调用方法3test(new String[]{"水果","电器"});//调用方法4        }    static void test(String ... array){  //直接打印:System.out.println(array);for(String str:array){  //利用增强for遍历            System.out.println(str);
            }
        }
ログイン後にコピー

なぜ可変パラメータを思い出すかというと、それがリフレクションの応用に似ているからです。メソッドが可変パラメーターとして定義されている場合、呼び出し時にパラメーターを渡す際の制限が大幅に軽減されます。リフレクションでは、いくつかのメソッドを使用してクラスのインスタンス オブジェクトを取得すると、クラス内のメソッド、属性などの全体像を表示できます。前回の研究で学んだように、メソッドやプロパティなどは静的と非静的、プライベートと非プライベートに分けられるため、呼び出し時にどの部分を取得したいのか、どの部分だけを取得したいのかが決まります。これを達成する方法を考えることはできますか?この時、反省が現れ、今、私が理解しているのはこれだけです。それを維持する。

1. リフレクションの概念

JAVA リフレクション メカニズムは実行状態にあります (コンパイル時ではないことに注意してください)。どのクラスでも、このクラスのすべてのプロパティとメソッドを知ることができます。この動的に取得された情報とオブジェクトのメソッドを動的に呼び出す機能は、Java 言語のリフレクション機構と呼ばれます。

Java リフレクション メカニズムは主に次の機能を提供します:

-- 実行時にオブジェクトが属するクラスを判断します。

-- 実行時に任意のクラスのオブジェクトを構築します。

-- 実行時に任意のクラスを判断します。クラスが所有する変数とメソッド

-- 実行時に任意のオブジェクトのメソッドを呼び出します。

-- 動的プロキシを生成します。

JDK では、リフレクションに関連するクラスには主に次のものが含まれます

//java.lang パッケージ

Class クラス

Class クラスのインスタンスは、実行中の Java アプリケーション内のクラスとインターフェイスを表します。列挙はクラスであり、アノテーションはインターフェイスです。各配列は、Class オブジェクトにマップされるクラスに属し、同じ要素の型と次元を持つすべての配列で共有されます。基本的な Java 型 (boolean、byte、char、short、int、long、float、double) とキーワード void も Class オブジェクトとして表されます。

ClassクラスJDK内の説明について:

public finalclass Class<T> implements java.io.Serializable,
                              java.lang.reflect.GenericDeclaration,
                              java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {private static final int ANNOTATION= 0x00002000;private static final int ENUM      = 0x00004000;private static final int SYNTHETIC = 0x00001000;private static native void registerNatives();static {
        registerNatives();
    }/* * Constructor. Only the Java Virtual Machine creates Class
     * objects.     */private Class() {}
ログイン後にコピー

ClassクラスJDK内のいくつかのメソッド(個人的に非常に読みやすいと感じたので記録しておきたい)

public String toString() {return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))+ getName();
    }//应该是三元表达式
ログイン後にコピー
public static Class<?> forName(String className)throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }
ログイン後にコピー
public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)throws ClassNotFoundException
    {
        Class<?> caller = null;
        SecurityManager sm = System.getSecurityManager();if (sm != null) {// Reflective call to get caller class is only needed if a security manager// is present.  Avoid the overhead of making this call otherwise.caller = Reflection.getCallerClass();if (loader == null) {
                ClassLoader ccl = ClassLoader.getClassLoader(caller);if (ccl != null) {
                    sm.checkPermission(
                        SecurityConstants.GET_CLASSLOADER_PERMISSION);
                }
            }
        }return forName0(name, initialize, loader, caller);
    }
ログイン後にコピー
private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)throws ClassNotFoundException;
ログイン後にコピー
public T newInstance()throws InstantiationException, IllegalAccessException
    {if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }// NOTE: the following code may not be strictly correct under// the current Java memory model.// Constructor lookupif (cachedConstructor == null) {if (this == Class.class) {throw new IllegalAccessException("Can not call newInstance() on the Class for java.lang.Class");
            }try {
                Class<?>[] empty = {};final Constructor<T> c = getConstructor0(empty, Member.DECLARED);// Disable accessibility checks on the constructor// since we have to do the security check here anyway// (the stack depth is wrong for the Constructor's// security check to work)                java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {public Void run() {
                                c.setAccessible(true);return null;
                            }
                        });
                cachedConstructor = c;
            } catch (NoSuchMethodException e) {throw new InstantiationException(getName());
            }
        }
        Constructor<T> tmpConstructor = cachedConstructor;// Security check (same as in java.lang.reflect.Constructor)int modifiers = tmpConstructor.getModifiers();if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();if (newInstanceCallerCache != caller) {
                Reflection.ensureMemberAccess(caller, this, null, modifiers);
                newInstanceCallerCache = caller;
            }
        }// Run constructortry {return tmpConstructor.newInstance((Object[])null);
        } catch (InvocationTargetException e) {
            Unsafe.getUnsafe().throwException(e.getTargetException());// Not reachedreturn null;
        }
    }
ログイン後にコピー
public String getName() {
        String name = this.name;if (name == null)this.name = name = getName0();return name;
    }
ログイン後にコピー
// cache the name to reduce the number of calls into the VMprivate transient String name;private native String getName0();
ログイン後にコピー

他にもたくさんあるので今は記録しません。 。 。 。 。

//java.lang.reflect  包下
Constructor 代表构造函数
Method 代表方法
Field 代表字段
Array 与数组相关
ログイン後にコピー

2. クラス class の説明

常用的得到Class类的方法 // Class c=new Class(); 不可以,因为它被私有化了1) Class c=Student.class;   //用类名.class 就可以得到Class类的实例2) Student stu=new Student();
Class c=stu.getClass();   //用对象名.getClass();3) Class c=Class.forName("com.mysql.jdbc.Driver");
ログイン後にコピー
//例一  通过调用无参的构造函数,创建类对象public class Test {public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    Class clazz=Dog.class;
    Dog dog=(Dog)clazz.newInstance();
    dog.shout();
    }
}            
class Dog{void shout(){
    System.out.println("汪汪");
    }
}
ログイン後にコピー

例 1 では、リフレクションを使用する利点がわかりませんでした。リフレクション

の他のクラスの説明 1) Constructor
はクラスのコンストラクターを表します クラスには以下の4つのメソッドが用意されています

public Constructor[] getConstructors() //クラス内のpublicをすべて返します Constructorコレクション、デフォルトのコンストラクターの添え字は 0 です

public Constructor getConstructor(Class...parameterTypes) //指定されたパブリック コンストラクターを返します。パラメーターはコンストラクターのパラメーター タイプです。コレクション

public Constructor< ;?> [] getDeclaredConstructors() //プライベート

public Constructorgt; getDeclaredConstructor(Class...parameterTypes) //プライベート

//例二 上例的改写Class clazz=Class.forName("com.weiboo.Dog"); //注意,必须是类的全部Dog dog=(Dog)clazz.newInstance();
dog.shout();
ログイン後にコピー

//例三  (运行本类,Dog 和 Cat 类,必须有一个无参的构造函数)public class Test {public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    Dog dog=(Dog)createObj(Dog.class);
    dog.shout();
                
    Cat cat=(Cat)createObj(Cat.class);
    cat.speak();
    }                    
static Object createObj(Class clazz) throws InstantiationException, IllegalAccessException{return clazz.newInstance();  //调用的是newInstance() 方法创建的类对象,它调用的是类中无参的构造方法}
    }        
class Dog{void shout(){
    System.out.println("汪汪");
    }
}        
class  Cat{void speak(){
    System.out.println("喵~~~");        
    }
}
ログイン後にコピー
を含む、指定されたコンストラクターをすべて返します

2) Method はクラス内のメソッドを表します

Class クラスには次の 4 つのメソッドが用意されています
public Method[] getMethods() //すべてのパブリック メソッドのコレクションを取得します

Inherited

public Method getMethod( String name,Class...parameterTypes) // 指定されたパブリック メソッドを取得します。 パラメータ 1: メソッド名 パラメータ 2: パラメータの型を設定します

public Method[] getDeclaredMethods() / / すべてのメソッドを取得します (拡張プライベート メソッドを含む) )、継承された

public Method getDeclaredMethod(String name,Class...parameterTypes) // 継承された

import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;//例子 得到某个类中指定的某个构造函数所对应的 Constructor对象class Test2 {public static void main(String[] args) throws InstantiationException,
            IllegalAccessException, ClassNotFoundException,
            NoSuchMethodException, SecurityException, IllegalArgumentException,
            InvocationTargetException {
        Class<Cat> clazz = Cat.class;

        Constructor<Cat> c = clazz.getConstructor(int.class, String.class);
        Cat cat = (Cat) c.newInstance(20, "加飞猫");
        cat.speak();
    }class Cat {private String name;private int age;public Cat(int age, String name) {this.age = age;this.name = name;
        }public Cat(String content) {
            System.out.println("这是构造函数得到的参数" + content);
        }void speak() {
            System.out.println("喵~~~");
            System.out.println("我的名字是" + this.name + "我的年龄是" + this.age);
        }
    }
}
ログイン後にコピー

/例子 访问类中的私有构造函数
Class clazz=Cat.class;
Constructor c=clazz.getDeclaredConstructor();
c.setAccessible(true);  //让私有成员可以对外访问Cat cat=(Cat) c.newInstance();  //对于私有的来说,能不能行?cat.speak();
ログイン後にコピー

を除く、指定されたメソッドを取得します

3) Field 代表字段

public Field getDeclaredField(String name)  // 获取任意指定名字的成员

public Field[] getDeclaredFields()  // 获取所有的成员变量,除了继承来的

public Field getField(String name)  // 获取任意public成员变量,包含继承来的

public Field[] getFields() // 获取所有的public成员变量

//例子 访问字段public class Test {public static void main(String[] args) throws Exception {
    Class clazz=Cat.class;                         /* Field field= clazz.getField("home");
    Cat c=new Cat();
    Object obj=field.get(c);
    System.out.println(obj); // 家*/ 
    Cat cat=new Cat();
    Field  [] fieldList= clazz.getDeclaredFields();for(Field f:fieldList){  //访问所有字段f.setAccessible(true);
    System.out.println(f.get(cat)); 
                                   }
        }
}                            
class  Cat{private String name="黑猫";private int age=2;public String home="家";
}
ログイン後にコピー

四、反射的应用

用一个例子来说明一下,比较两个同类对象中的所有字段,不同的并把它输出来。

import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class Test {public static void main(String[] args) throws Exception {
        Student stu1 = new Student(24, "李磊", "工程大学", "女");
        Student stu2 = new Student(20, "王一", "师大", "男");
        Map<String, String> map = compare(stu1, stu2);for (Map.Entry<String, String> item : map.entrySet()) {
            System.out.println(item.getKey() + ":" + item.getValue());
        }
    }static Map<String, String> compare(Student stu1, Student stu2) {
        Map<String, String> resultMap = new HashMap<String, String>();

        Field[] fieldLis = stu1.getClass().getDeclaredFields(); // 得到stu1所有的字段对象try {for (Field f : fieldLis) {
                f.setAccessible(true); // 别忘了,让私有成员可以对外访问Object v1 = f.get(stu1);
                Object v2 = f.get(stu2);if (!(v1.equals(v2))) {
                    resultMap.put(f.getName(), "stu1的值是" + v1 + "   stu2的值是"
                            + v2);
                }
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }return resultMap;

    }

}class Student {private String name;private String school;private String sex;public Student(int age, String name, String school, String sex) {this.age = age;this.name = name;this.school = school;this.sex = sex;
    }private int age;public int getAge() {return age;
    }public void setAge(int age) {this.age = age;
    }public String getName() {return name;
    }public void setName(String name) {this.name = name;
    }public String getSchool() {return school;
    }public void setSchool(String school) {this.school = school;
    }public String getSex() {return sex;
    }public void setSex(String sex) {this.sex = sex;
    }
}
ログイン後にコピー

以上がリフレクション、Java の基本入門の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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