java 利用反射建立對象

建立對象:java

一、使用Class對象的newInstance()方法建立該Class對象的實例,此時該Class對象必需要有無參數的構造方法。安全

二、使用Class對象獲取指定的Constructor對象,再調用Constructor的newInstance()方法建立對象類的實例,此時能夠選擇使用某個構造方法。若是這個構造方法被私有化起來,那麼必須先申請訪問,將能夠訪問設置爲true;ide

 

Eg:對象

最簡單的:get

package junereflect624;it

 

class User{io

    /*private User(){//將默認的構造方法私有化的話就不能夠再建立對象,兩種方法都是這樣編譯

    }*/class

    public String toString() {import

        return "User對象建立成功!";

    }

}

 

public class NewInstanceDemo6 {

    public static void main(String[] args) throws Exception {

        //傳統方式建立對象

         System.out.println(new User());

         

         //使用反射的方式

         Class<User> c = User.class;

         User u = c.newInstance();(直接newInstance的話必須保證默認的構造方法正常存在,也就是沒有被私有化!這是前提條件)

         System.out.println(u);

    }

}

 

 

複雜點的:更強大的第二種:

 

使用指定構造方法來建立對象:

獲取該類的Class對象。

利用Class對象的getConstructor()方法來獲取指定的構造方法。

調用Constructor的newInstance()方法建立對象。

 

AccessibleObject對象的setAccessible(boolean flag)方法,當flag爲true的時候,就會忽略訪問權限(可訪問私有的成員)。

其子類有Field, Method, Constructor;

若要訪問對象private的成員?

在調用以前使用setAccessible(true),

       Xxx x = getDeclaredXxxx();//才能獲得私有的類字段.

 

總結步驟:

 

  1. 1.        獲取該類的Class對象。
  2. 2.        利用Class對象的getConstructor()方法來獲取指定的構造方法。
  3. 3.        申請訪問(設置爲可訪問)
  4. 4.  調用Constructor(構造方法)的newInstance()方法建立對象。

 

例子

package junereflect624;

 

import java.lang.reflect.Constructor;

 

class Per{

    private String name;

    private int age;

    private Per(){   

    }

    private Per(String name){

    }

    public String toString() {

        return "對象!!!";

    }

}

 

public class NewInstanceDemo7 {

    public static void main(String[] args) throws Exception {

        Class<Per> c = Per.class;

        //System.out.println(c.newInstance());;//證實利用無參的能夠

       

        ////先得到須要被調用的構造器(private 修飾的構造方法)

        Constructor<Per> con = c.getDeclaredConstructor();//調用默認的,什麼都不要寫

        System.out.println(con);//private junereflect624.Per()

        /*con = c.getDeclaredConstructor(String.class);獲取指定的構造方法

        System.out.println(con);//private junereflect624.Per(java.lang.String)*/     

        //如今只須要執行這個構造器,

        /**

         *  T newInstance(Object... initargs)

                使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新實例,並用指定的初始化參數初始化該實例。

         */

       

        //私有的成員是受保護的,不能直接訪問

        //若要訪問私有的成員,得先申請一下

        con.setAccessible(true);//容許訪問

        Per p = con.newInstance();//成功,經過私有的受保護的構造方法建立了對象

        System.out.println("無參構造方法"+p);

       

        con = c.getDeclaredConstructor(String.class);

        System.out.println(con);//private junereflect624.Per(java.lang.String)

           

        con.setAccessible(true);//容許訪問

        p = con.newInstance("liuzhao");//成功,經過私有的受保護的構造方法建立了對象

        System.out.println("String構造方法"+p);

    }

}

備註:對於此時的話,單例模式就再也不安全了!反射可破之!!

 

 

 

驗證:對於枚舉而言,反射依然沒有辦法從新建立對象

對於枚舉,安全!

 

package junereflect624;

 

import java.lang.reflect.Constructor;

 

enum Color{

    RED,BLUE,GREEN;

    private Color(){

    }

}

 

public class EnumDemo8 {

    public static void main(String[] args) throws Exception {

        Class<Color> c = Color.class;

       

        Constructor<Color> con = c.getDeclaredConstructor();//(錯誤在這一行發生,就是說對枚舉而言這種方法連構造器都得到不了,)編譯能夠經過,可是運行就通不過了!

        Color co = (Color) con.newInstance();

        System.out.println(co);//失敗,證實對枚舉而言不行,因此枚舉的單例模式更加安全

        System.out.println(c.isEnum());//true是枚舉

    }

}

相關文章
相關標籤/搜索