java反射機制(一)

一.JAVA反射機制:
JAVA反射機制是指在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。

二.Class類:
在Java中,每個class都有一個相應的Class對象。也就是說,當我們編寫一個類,編譯完成後,在生成的.class文件中,就會產生一個Class對象,用於表示這個類的類型信息。
Class類是一切反射的根源。
eg:很多車—>car類
很多人—>person類
很多類—>Class類

三.Class類的應用:

  1. 獲得Class對象的3種形式
  2. 調用Class類的默認無參構造方法實例化類對象
  3. 獲取所有的構造方法
  4. 獲取類屬性
  5. 獲取類包名與方法

程序Dog類:

public class Dog {
    private String name;
    private int age;
    private String color;

    private String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public Dog() {
    }

    public Dog(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }
}

1.如何獲取Class對象?
①對象.getClass()
②類.class
③Class.forname(類名)

eg1:

     /*
    獲取Class對象的三種形式
     */
    @Test
    public void test1() {
        //通過對象的getclass方法(有對象的時候用)
        Dog dog = new Dog("mike", 5, "white");
        Class<? extends Dog> aClass = dog.getClass();   //泛型

        //通過類.class(直到類的時候用)
        Class<Dog> dogClass = Dog.class;

        //通過Class.forname方法(只知道類名字符串時候用)
        try {
            Class<?> aClass1 = Class.forName("com.sihengReflection.Dog");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.利用Class類對象實例化Dog類對象,調用了Class類的默認無參構造方法
注:newInstance(): 弱類型。低效率。只能調用無參構造

eg2:

public void test2() {
        Class<Dog> dogClass = Dog.class;
        //通過Class類對象實例化Dog類對象,調用了Class類的默認無參構造方法
        try {
            Dog dog = (Dog) dogClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

3.獲取所有的構造方法:

eg3:

@Test
    public void test3() {
        Class<Dog> dogClass = Dog.class;//獲取類對象
        Constructor<?>[] constructors = dogClass.getConstructors();//獲取構造方法集合
        for (int i = 0; i < constructors.length; i++) {
            System.out.println(constructors[i].getName());//方法名稱
            System.out.println(constructors[i].getParameterCount());//方法參數個數
        }
        //可以獲取有參構造方法的參數數組,constructors[0]是無參的,也可以獲取參數數組,不報錯
        Class<?>[] parameterTypes = constructors[1].getParameterTypes();
        System.out.println(parameterTypes[0].getName());

        //調用構造方法dogClass.getConstructor獲取一個
        try {
            //獲取一個特定的構造方法
            Constructor<Dog> constructors1 = dogClass.getConstructor(String.class, int.class, String.class);
            //調用帶參數的構造器來實例化對象
            Dog dog = constructors1.newInstance("狗子", 2, "白色");//因爲構造方法的實例就是dog對象
            System.out.println(dog.getAge()+"歲");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

輸出:
com.sihengReflection.Dog
0
com.sihengReflection.Dog
3
java.lang.String
2歲

4.獲取所有屬性:

eg4:

@Test
    public void test4() {
        Class<Dog> dogClass = Dog.class;
        //獲取非私有屬性
        Field[] fields = dogClass.getFields();
        System.out.println(fields.length);//只能獲取到共有屬性,所以這裏值爲零

        //獲取所有屬性
        Field[] declaredFields = dogClass.getDeclaredFields();//Declared顧名思義,定義了的都可以獲取
        System.out.println(declaredFields.length);

        //輸出來
        for (int i = 0; i < declaredFields.length; i++) {
            int modifiers = declaredFields[i].getModifiers();//修飾符--->整形--->要強轉換
            System.out.println(Modifier.toString(modifiers) + "  " + declaredFields[i].getType() + "  " + declaredFields[i]
                    .getName());
        }
    }

輸出:
0
3
private class java.lang.String name
private int age
private class java.lang.String color

5.獲取包名與方法:

eg5:

@Test
    public void test5() {
        Dog dog = new Dog("mike", 4, "白色");//先實例化一個Dog對象
        Class<Dog> dogClass = Dog.class;//獲取一個類對象
        Package aPackage = dogClass.getPackage();//包
        System.out.println(aPackage.getName());

        //獲取共有的方法,包括繼承的共有方法
        Method[] methods = dogClass.getMethods();//獲取方法

        for (int i = 0; i < methods.length; i++) {
            System.out.println(methods[i]);

            if (methods[i].getName().equals("toString")) {  //利用一下toString()
                try {
                    String s = (String) methods[i].invoke(dog);  //invoke(方法作用的對象,方法參數),這裏toString並無參數
                    System.out.println("toString:  "+s);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("--------我是可愛的分割線--------");

        //訪問私有方法,6的不行
        Method[] declaredMethods = dogClass.getDeclaredMethods();//獲取所有定義了的方法,包括私有方法,但是沒有繼承(父類的)的方法
        for (int i = 0; i < declaredMethods.length; i++) {
            System.out.println(declaredMethods[i]);   //獲取所有定義了的方法
            if (declaredMethods[i].getName().equals("getName")) {
                System.out.println("我可以調用私有方法啦");

                declaredMethods[i].setAccessible(true);//必須設置方法可以訪問纔可以訪問這個私有方法

                try {
                    String name = (String) declaredMethods[i].invoke(dog);
                    System.out.println("我的名字:" + name);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

輸出:
com.sihengReflection
public java.lang.String com.sihengReflection.Dog.toString()
toString: Dog{name=’mike’, age=4, color=’白色’}
public void com.sihengReflection.Dog.setName(java.lang.String)
public void com.sihengReflection.Dog.setColor(java.lang.String)
public int com.sihengReflection.Dog.getAge()
public void com.sihengReflection.Dog.setAge(int)
public java.lang.String com.sihengReflection.Dog.getColor()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
——–我是可愛的分割線——–
public java.lang.String com.sihengReflection.Dog.toString()
private java.lang.String com.sihengReflection.Dog.getName()
我可以調用私有方法啦
我的名字:mike
public void com.sihengReflection.Dog.setName(java.lang.String)
public void com.sihengReflection.Dog.setColor(java.lang.String)
public int com.sihengReflection.Dog.getAge()
public void com.sihengReflection.Dog.setAge(int)
public java.lang.String com.sihengReflection.Dog.getColor()

四.總結:
給我的感覺就是反射無視了java的封裝。學習反射有利於後續學習java ee時理解框架的原理。

發佈了35 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章