反射

 

類的加載

當程序要使用某個類時,若是該類還未被加載到內存中,則系統會經過加載,鏈接,初始化來實現對這個類進行初始化

       加載: 將class文件讀入內存, 併爲之建立一個Class對象; 任何類被使用時系統都會創建一個Class對象

       鏈接

驗證: 是否有正確的內部結構, 並和其餘類協調一致

              準備: 負責爲類的靜態成員分配內存, 並設置默認初始化值

              解析: 將類的二進制數據中的符號引用替換爲直接引用

       初始化java

                以前的new一個對象的初始化步驟

類加載器

將class文件加載到內存,併爲之生成對應的Class對象

類加載器的組成

       Bootstrap ClassLoader 根類加載器

              引導類加載器: 負責Java核心類的加載

                     好比system,String等。在JDK中JRE的lib目錄下rt.jar文件中

       Extension ClassLoader 擴展類加載器

              負責JRE的擴展目錄中jar包的加載

                     在JDK中JRE的lib目錄下ext目錄

       System ClassLoader 系統類加載器

              負責在JVM啓動時加載來自Java命令的class文件,以及classpath環境變量所指定的jar包或類路徑

反射: 獲取class文件對象的三種方式

//方式1
Person p = new Person();
Class c = p.getClass();

Person p2 = new Person();
Class c2 = p2.getClass();
//false
System.out.println(p == p2);
//true
System.out.println(c == c2);

//方式2
Class c3 = Person.class;
//true
System.out.println(c == c3);
//方式3F:
Class c4=Class.forName("Person");
Class c4 = Class.forName("xx.xxxx.Person");

反射獲取構造方法

//public Constructor<?>[] getConstructors()獲取本類(不包括父類)全部公共(只能是public修飾的)的構造方法
Constructor[] cons=c.getConstructors();
for (Constructor con:cons){
    System.out.println(con);
}
/**public cn.itcast_01.Person()*/
//public Constructor<?>[] getDeclaredConstructors() 獲得在本類(不包括父類)書寫的構造方法(不受訪問修飾符限制)
Constructor[] cons=c.getDeclaredConstructors();
for (Constructor con:cons){
    System.out.println(con);
}
/**protected cn.itcast_01.Person(java.lang.String,int,java.lang.String)
cn.itcast_01.Person(java.lang.String,int)
private cn.itcast_01.Person(java.lang.String)
public cn.itcast_01.Person()*/
//獲取單個構造方法(只能是public修飾的);參數表示的是: 你要獲取的構造方法的構造參數個數及數據類型的class字節碼文件對象
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor cons = c.getConstructor();
Object obj=cons.newInstance();
System.out.println(obj);
/**Person{name='null', age=0, address='null'}*/
//獲取單個構造方法(不受訪問修飾符的限制)
//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor cons = c.getDeclaredConstructor(String.class, int.class, String.class);//返回的構造方法對象
//Constructor類的:public T newInstance(Object... initargs)使用此Constructor對象表示的
//構造方法的聲明類的新實例,並用指定的初始化參數初始化該實例
// 暴力訪問
 cons.setAccessible(true);
 Object obj=cons.newInstance("120", 1 ,"蛋蛋");
/**Person{name='120', age=1, address='蛋蛋'}*/
//獲取全部的成員變量(當前類及父類被public修飾的)
Field[] fields=c.getFields();
//獲取全部的成員變量 (只能是本類的(不受訪問修飾符的限制)), (but excludes inherited fields)不包括從父類的
Field[] fields=c.getDeclaredFields();
Class c=Class.forName("cn.itcast_01.Person");
Constructor cons = c.getConstructor();
Object obj = cons.newInstance();
Field addressField = c.getField("address");
addressField.set(obj,"北京");
System.out.println(obj);
/**Person{name='null', age=0, address='北京'}*/
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj,"");
System.out.println(obj);
/**Person{name='青', age=0, address='北京'}*/
// 獲取本身的方法, 繼承而來的包括Object類的方法, 都只能是public修飾的
 Method[] methods=c.getMethods();
//獲取本身的全部方法,包括從父類繼承的public修飾的方法 不包括Object類的
Method[] methods = c.getDeclaredMethods();
Class c = Class.forName("cn.itcast_01.Person");
Constructor cons = c.getConstructor();
Object obj = cons.newInstance();
Method method2 = c.getMethod("getString", String.class, int.class);
Object objString = method2.invoke(obj, "hellojava", 100);
System.out.println(objString);/**hellojava---100*/

ArrayList<Integer>的一個對象,在這個集合中添加一個字符串數據,如何實現呢?

public static void main(String[] args) throws Exception {
    //建立集合對象
    ArrayList<Integer> arrayList = new ArrayList<>();
    //添加數據
    arrayList.add(120);
    //集合ArrayList的class文件對象
    Class c = arrayList.getClass();
    Method method = c.getMethod("add", Object.class);
    method.invoke(arrayList, "hello");
    method.invoke(arrayList, "world");
    method.invoke(arrayList, "java");
    arrayList.add(30);
    // public boolean java.util.ArrayList.add(java.lang.Object)
    System.out.println(method);
    // [120, hello, world, java, 30]
    System.out.println(arrayList);

}
public void setProperty(Object obj, String propertyName, Object value) throws Exception {
    //獲取字節碼文件對象
    Class c=obj.getClass();
    //獲取該對象的propertyName的成員變量
    Field field=c.getDeclaredField(propertyName);
    //取消訪問檢查
    field.setAccessible(true);
    //給對象的成員變量propertyName賦值爲指定的值
    field.set(obj,value);

}

 

動態代理

JDK提供的代理只能針對接口作代理
public interface UserDao {
    void add();
    void delete();
    void update();
    void find();
}
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("添加功能");
    }

    @Override
    public void delete() {
        System.out.println("刪除功能");
    }

    @Override
    public void update() {
        System.out.println("修改功能");
    }

    @Override
    public void find() {
        System.out.println("查找功能");
    }
}
public interface StudentDao {
    void login();
    void regist();
}
public class StudenDaotImpl implements StudentDao {
    @Override
    public void login() {
        System.out.println("登陸功能");
    }

    @Override
    public void regist() {
        System.out.println("註冊功能");
    }
}
public class MyInvocationHandler implements InvocationHandler{
    /**目標對象*/
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    /**
     * Object invoke(Object proxy, Method method, Object[] args)
     * 在代理實例上處理方法調用並返回結果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("權限校驗");
        Object result=method.invoke(target,args);
        System.out.println("日誌記錄");
        // 返回的是代理對象
        return result;
    }
}

 

public static void main(String[] args) {
    UserDao ud = new UserDaoImpl();
    ud.add();
    ud.delete();
    ud.update();
    ud.find();
    /*添加功能
      刪除功能
      修改功能
      查找功能*/
    System.out.println("------------");
    //我要建立一個動態代理對象 Proxy類中有一個方法能夠建立動態代理對象
    //public static Object newProxyInstance(ClassLoader loader,
    //Class<?>[] interfaces,InvocationHandler h)
    //對ud對象作一個代理對象
    MyInvocationHandler handler = new MyInvocationHandler(ud);
    UserDao proxy = (UserDao) Proxy.newProxyInstance
            (ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), handler);
    proxy.add();
    proxy.delete();
    proxy.update();
    proxy.find();
    /*權限校驗
    添加功能
    日誌記錄
    權限校驗
    刪除功能
    日誌記錄
    權限校驗
    修改功能
    日誌記錄
    權限校驗
    查找功能
    日誌記錄*/
    System.out.println("-------------");
    StudentDao sd = new StudenDaotImpl();
    MyInvocationHandler handler1 = new MyInvocationHandler(sd);
    StudentDao proxy1 = (StudentDao) Proxy.newProxyInstance(sd.getClass().getClassLoader(),
            sd.getClass().getInterfaces(), handler1);
    proxy1.login();
    proxy1.regist();
    /*權限校驗
      登陸功能
      日誌記錄
      權限校驗
      註冊功能
      日誌記錄*/

}
相關文章
相關標籤/搜索