国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java反射深入剖析(推薦)

2019-11-26 14:02:15
字體:
供稿:網(wǎng)友

本篇文章依舊采用小例子來說明,因為我始終覺的,案例驅(qū)動是最好的,要不然只看理論的話,看了也不懂,不過建議大家在看完文章之后,在回過頭去看看理論,會有更好的理解。

下面開始正文。

【案例1】通過一個對象獲得完整的包名和類名

package Reflect;  /**  * 通過一個對象獲得完整的包名和類名  * */class Demo{   //other codes... }  class hello{   public static void main(String[] args) {     Demo demo=new Demo();     System.out.println(demo.getClass().getName());   } }

【運行結(jié)果】:Reflect.Demo

添加一句:所有類的對象其實都是Class的實例。

【案例2】實例化Class類對象

package Reflect; class Demo{   //other codes... }  class hello{   public static void main(String[] args) {     Class<?> demo1=null;     Class<?> demo2=null;     Class<?> demo3=null;     try{       //一般盡量采用這種形式       demo1=Class.forName("Reflect.Demo");     }catch(Exception e){       e.printStackTrace();     }     demo2=new Demo().getClass();     demo3=Demo.class;          System.out.println("類名稱  "+demo1.getName());     System.out.println("類名稱  "+demo2.getName());     System.out.println("類名稱  "+demo3.getName());        } }

【運行結(jié)果】:
類名稱   Reflect.Demo
類名稱   Reflect.Demo
類名稱   Reflect.Demo

【案例3】通過Class實例化其他類的對象

通過無參構(gòu)造實例化對象

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

然后繼續(xù)運行上面的程序,會出現(xiàn):

所以大家以后再編寫使用Class實例化其他類的對象的時候,一定要自己定義無參的構(gòu)造函數(shù)
 
【案例】通過Class調(diào)用其他類中的構(gòu)造函數(shù) (也可以通過這種方式通過Class創(chuàng)建其他類的對象)

package Reflect;  import java.lang.reflect.Constructor;  class Person{      public Person() {        }   public Person(String name){     this.name=name;   }   public Person(int age){     this.age=age;   }   public Person(String name, int age) {     this.age=age;     this.name=name;   }   public String getName() {     return name;   }   public int getAge() {     return age;   }   @Override  public String toString(){     return "["+this.name+" "+this.age+"]";   }   private String name;   private int age; }  class hello{   public static void main(String[] args) {     Class<?> demo=null;     try{       demo=Class.forName("Reflect.Person");     }catch (Exception e) {       e.printStackTrace();     }     Person per1=null;     Person per2=null;     Person per3=null;     Person per4=null;     //取得全部的構(gòu)造函數(shù)     Constructor<?> cons[]=demo.getConstructors();     try{       per1=(Person)cons[0].newInstance();       per2=(Person)cons[1].newInstance("Rollen");       per3=(Person)cons[2].newInstance(20);       per4=(Person)cons[3].newInstance("Rollen",20);     }catch(Exception e){       e.printStackTrace();     }     System.out.println(per1);     System.out.println(per2);     System.out.println(per3);     System.out.println(per4);   } }

【運行結(jié)果】:

[null  0]
[Rollen  0]
[null  20]
[Rollen  20]

【案例】

返回一個類實現(xiàn)的接口:

package Reflect;  interface China{   public static final String name="Rollen";   public static int age=20;   public void sayChina();   public void sayHello(String name, int age); }  class Person implements China{   public Person() {        }   public Person(String sex){     this.sex=sex;   }   public String getSex() {     return sex;   }   public void setSex(String sex) {     this.sex = sex;   }   @Override  public void sayChina(){     System.out.println("hello ,china");   }   @Override  public void sayHello(String name, int age){     System.out.println(name+" "+age);   }   private String sex; }  class hello{   public static void main(String[] args) {     Class<?> demo=null;     try{       demo=Class.forName("Reflect.Person");     }catch (Exception e) {       e.printStackTrace();     }     //保存所有的接口     Class<?> intes[]=demo.getInterfaces();     for (int i = 0; i < intes.length; i++) {       System.out.println("實現(xiàn)的接口  "+intes[i].getName());     }   } }

【運行結(jié)果】:

實現(xiàn)的接口   Reflect.China

(注意,以下幾個例子,都會用到這個例子的Person類,所以為節(jié)省篇幅,此處不再粘貼Person的代碼部分,只粘貼主類hello的代碼)

【案例】:取得其他類中的父類

class hello{   public static void main(String[] args) {     Class<?> demo=null;     try{       demo=Class.forName("Reflect.Person");     }catch (Exception e) {       e.printStackTrace();     }     //取得父類     Class<?> temp=demo.getSuperclass();     System.out.println("繼承的父類為:  "+temp.getName());   } } 

【運行結(jié)果】

繼承的父類為:   java.lang.Object

【案例】:獲得其他類中的全部構(gòu)造函數(shù)

這個例子需要在程序開頭添加import java.lang.reflect.*;
然后將主類編寫為:

class hello{   public static void main(String[] args) {     Class<?> demo=null;     try{       demo=Class.forName("Reflect.Person");     }catch (Exception e) {       e.printStackTrace();     }     Constructor<?>cons[]=demo.getConstructors();     for (int i = 0; i < cons.length; i++) {       System.out.println("構(gòu)造方法: "+cons[i]);     }   } }

【運行結(jié)果】:

構(gòu)造方法:  public Reflect.Person()
構(gòu)造方法:  public Reflect.Person(java.lang.String)

但是細心的讀者會發(fā)現(xiàn),上面的構(gòu)造函數(shù)沒有public 或者private這一類的修飾符

下面這個例子我們就來獲取修飾符

class hello{   public static void main(String[] args) {     Class<?> demo=null;     try{       demo=Class.forName("Reflect.Person");     }catch (Exception e) {       e.printStackTrace();     }     Constructor<?>cons[]=demo.getConstructors();     for (int i = 0; i < cons.length; i++) {       Class<?> p[]=cons[i].getParameterTypes();       System.out.print("構(gòu)造方法: ");       int mo=cons[i].getModifiers();       System.out.print(Modifier.toString(mo)+" ");       System.out.print(cons[i].getName());       System.out.print("(");       for(int j=0;j<p.length;++j){         System.out.print(p[j].getName()+" arg"+i);         if(j<p.length-1){           System.out.print(",");         }       }       System.out.println("){}");     }   } }

【運行結(jié)果】:

構(gòu)造方法:  public Reflect.Person(){}
構(gòu)造方法:  public Reflect.Person(java.lang.String arg1){}

有時候一個方法可能還有異常,呵呵。下面看看:

class hello{   public static void main(String[] args) {     Class<?> demo=null;     try{       demo=Class.forName("Reflect.Person");     }catch (Exception e) {       e.printStackTrace();     }     Method method[]=demo.getMethods();     for(int i=0;i<method.length;++i){       Class<?> returnType=method[i].getReturnType();       Class<?> para[]=method[i].getParameterTypes();       int temp=method[i].getModifiers();       System.out.print(Modifier.toString(temp)+" ");       System.out.print(returnType.getName()+" ");       System.out.print(method[i].getName()+" ");       System.out.print("(");       for(int j=0;j<para.length;++j){         System.out.print(para[j].getName()+" "+"arg"+j);         if(j<para.length-1){           System.out.print(",");         }       }       Class<?> exce[]=method[i].getExceptionTypes();       if(exce.length>0){         System.out.print(") throws ");         for(int k=0;k<exce.length;++k){           System.out.print(exce[k].getName()+" ");           if(k<exce.length-1){             System.out.print(",");           }         }       }else{         System.out.print(")");       }       System.out.println();     }   } }
【運行結(jié)果】:

【案例】接下來讓我們?nèi)〉闷渌惖娜繉傩园桑詈笪抑v這些整理在一起,也就是通過class取得一個類的全部框架

class hello {   public static void main(String[] args) {     Class<?> demo = null;     try {       demo = Class.forName("Reflect.Person");     } catch (Exception e) {       e.printStackTrace();     }     System.out.println("===============本類屬性========================");     // 取得本類的全部屬性     Field[] field = demo.getDeclaredFields();     for (int i = 0; i < field.length; i++) {       // 權(quán)限修飾符       int mo = field[i].getModifiers();       String priv = Modifier.toString(mo);       // 屬性類型       Class<?> type = field[i].getType();       System.out.println(priv + " " + type.getName() + " "          + field[i].getName() + ";");     }     System.out.println("===============實現(xiàn)的接口或者父類的屬性========================");     // 取得實現(xiàn)的接口或者父類的屬性     Field[] filed1 = demo.getFields();     for (int j = 0; j < filed1.length; j++) {       // 權(quán)限修飾符       int mo = filed1[j].getModifiers();       String priv = Modifier.toString(mo);       // 屬性類型       Class<?> type = filed1[j].getType();       System.out.println(priv + " " + type.getName() + " "          + filed1[j].getName() + ";");     }   } }

【運行結(jié)果】:

===============本類屬性========================
private java.lang.String sex;
===============實現(xiàn)的接口或者父類的屬性========================
public static final java.lang.String name;
public static final int age;

【案例】其實還可以通過反射調(diào)用其他類中的方法:

class hello {   public static void main(String[] args) {     Class<?> demo = null;     try {       demo = Class.forName("Reflect.Person");     } catch (Exception e) {       e.printStackTrace();     }     try{       //調(diào)用Person類中的sayChina方法       Method method=demo.getMethod("sayChina");       method.invoke(demo.newInstance());       //調(diào)用Person的sayHello方法       method=demo.getMethod("sayHello", String.class,int.class);       method.invoke(demo.newInstance(),"Rollen",20);            }catch (Exception e) {       e.printStackTrace();     }   } }

【運行結(jié)果】:

hello ,china
Rollen  20

【案例】調(diào)用其他類的set和get方法

class hello {   public static void main(String[] args) {     Class<?> demo = null;     Object obj=null;     try {       demo = Class.forName("Reflect.Person");     } catch (Exception e) {       e.printStackTrace();     }     try{      obj=demo.newInstance();     }catch (Exception e) {       e.printStackTrace();     }     setter(obj,"Sex","男",String.class);     getter(obj,"Sex");   }    /**    * @param obj    *      操作的對象    * @param att    *      操作的屬性    * */  public static void getter(Object obj, String att) {     try {       Method method = obj.getClass().getMethod("get" + att);       System.out.println(method.invoke(obj));     } catch (Exception e) {       e.printStackTrace();     }   }    /**    * @param obj    *      操作的對象    * @param att    *      操作的屬性    * @param value    *      設(shè)置的值    * @param type    *      參數(shù)的屬性    * */  public static void setter(Object obj, String att, Object value,       Class<?> type) {     try {       Method method = obj.getClass().getMethod("set" + att, type);       method.invoke(obj, value);     } catch (Exception e) {       e.printStackTrace();     }   } }// end class

【運行結(jié)果】:

【案例】通過反射操作屬性

class hello {   public static void main(String[] args) throws Exception {     Class<?> demo = null;     Object obj = null;      demo = Class.forName("Reflect.Person");     obj = demo.newInstance();      Field field = demo.getDeclaredField("sex");     field.setAccessible(true);     field.set(obj, "男");     System.out.println(field.get(obj));   } }// end class 

【案例】通過反射取得并修改數(shù)組的信息:

import java.lang.reflect.*; class hello{   public static void main(String[] args) {     int[] temp={1,2,3,4,5};     Class<?>demo=temp.getClass().getComponentType();     System.out.println("數(shù)組類型: "+demo.getName());     System.out.println("數(shù)組長度 "+Array.getLength(temp));     System.out.println("數(shù)組的第一個元素: "+Array.get(temp, 0));     Array.set(temp, 0, 100);     System.out.println("修改之后數(shù)組第一個元素為: "+Array.get(temp, 0));   } } 

【運行結(jié)果】:

數(shù)組類型: int
數(shù)組長度  5
數(shù)組的第一個元素: 1
修改之后數(shù)組第一個元素為: 100

【案例】通過反射修改數(shù)組大小

class hello{   public static void main(String[] args) {     int[] temp={1,2,3,4,5,6,7,8,9};     int[] newTemp=(int[])arrayInc(temp,15);     print(newTemp);     System.out.println("=====================");     String[] atr={"a","b","c"};     String[] str1=(String[])arrayInc(atr,8);     print(str1);   }      /**    * 修改數(shù)組大小    * */  public static Object arrayInc(Object obj,int len){     Class<?>arr=obj.getClass().getComponentType();     Object newArr=Array.newInstance(arr, len);     int co=Array.getLength(obj);     System.arraycopy(obj, 0, newArr, 0, co);     return newArr;   }   /**    * 打印    * */  public static void print(Object obj){     Class<?>c=obj.getClass();     if(!c.isArray()){       return;     }     System.out.println("數(shù)組長度為: "+Array.getLength(obj));     for (int i = 0; i < Array.getLength(obj); i++) {       System.out.print(Array.get(obj, i)+" ");     }   } }

【運行結(jié)果】:

數(shù)組長度為: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
數(shù)組長度為: 8
a b c null null null null null


動態(tài)代理

【案例】首先來看看如何獲得類加載器:

class test{    } class hello{   public static void main(String[] args) {     test t=new test();     System.out.println("類加載器 "+t.getClass().getClassLoader().getClass().getName());   } } 

【程序輸出】:

類加載器  sun.misc.Launcher$AppClassLoader

其實在java中有三種類類加載器。

1)Bootstrap ClassLoader 此加載器采用c++編寫,一般開發(fā)中很少見。

2)Extension ClassLoader 用來進行擴展類的加載,一般對應(yīng)的是jre/lib/ext目錄中的類

3)AppClassLoader 加載classpath指定的類,是最常用的加載器。同時也是java中默認的加載器。

如果想要完成動態(tài)代理,首先需要定義一個InvocationHandler接口的子類,已完成代理的具體操作。

package Reflect; import java.lang.reflect.*;  //定義項目接口 interface Subject {   public String say(String name, int age); }  // 定義真實項目 class RealSubject implements Subject {   @Override  public String say(String name, int age) {     return name + " " + age;   } }  class MyInvocationHandler implements InvocationHandler {   private Object obj = null;    public Object bind(Object obj) {     this.obj = obj;     return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj         .getClass().getInterfaces(), this);   }    @Override  public Object invoke(Object proxy, Method method, Object[] args)       throws Throwable {     Object temp = method.invoke(this.obj, args);     return temp;   } }  class hello {   public static void main(String[] args) {     MyInvocationHandler demo = new MyInvocationHandler();     Subject sub = (Subject) demo.bind(new RealSubject());     String info = sub.say("Rollen", 20);     System.out.println(info);   } }

【運行結(jié)果】:
Rollen  20

類的生命周期

在一個類編譯完成之后,下一步就需要開始使用類,如果要使用一個類,肯定離不開JVM。在程序執(zhí)行中JVM通過裝載,鏈接,初始化這3個步驟完成。

類的裝載是通過類加載器完成的,加載器將.class文件的二進制文件裝入JVM的方法區(qū),并且在堆區(qū)創(chuàng)建描述這個類的java.lang.Class對象。用來封裝數(shù)據(jù)。 但是同一個類只會被類裝載器裝載以前

鏈接就是把二進制數(shù)據(jù)組裝為可以運行的狀態(tài)。
 
鏈接分為校驗,準備,解析這3個階段

校驗一般用來確認此二進制文件是否適合當前的JVM(版本),

準備就是為靜態(tài)成員分配內(nèi)存空間,。并設(shè)置默認值

解析指的是轉(zhuǎn)換常量池中的代碼作為直接引用的過程,直到所有的符號引用都可以被運行程序使用(建立完整的對應(yīng)關(guān)系)

完成之后,類型也就完成了初始化,初始化之后類的對象就可以正常使用了,直到一個對象不再使用之后,將被垃圾回收。釋放空間。

當沒有任何引用指向Class對象時就會被卸載,結(jié)束類的生命周期

將反射用于工廠模式

先來看看,如果不用反射的時候,的工廠模式吧:

/**  * @author Rollen-Holt 設(shè)計模式之 工廠模式  */ interface fruit{   public abstract void eat(); }  class Apple implements fruit{   public void eat(){     System.out.println("Apple");   } }  class Orange implements fruit{   public void eat(){     System.out.println("Orange");   } }  // 構(gòu)造工廠類 // 也就是說以后如果我們在添加其他的實例的時候只需要修改工廠類就行了 class Factory{   public static fruit getInstance(String fruitName){     fruit f=null;     if("Apple".equals(fruitName)){       f=new Apple();     }     if("Orange".equals(fruitName)){       f=new Orange();     }     return f;   } } class hello{   public static void main(String[] a){     fruit f=Factory.getInstance("Orange");     f.eat();   }  }

這樣,當我們在添加一個子類的時候,就需要修改工廠類了。如果我們添加太多的子類的時候,改的就會很多。

現(xiàn)在我們看看利用反射機制:

package Reflect;  interface fruit{   public abstract void eat(); }  class Apple implements fruit{   public void eat(){     System.out.println("Apple");   } }  class Orange implements fruit{   public void eat(){     System.out.println("Orange");   } }  class Factory{   public static fruit getInstance(String ClassName){     fruit f=null;     try{       f=(fruit)Class.forName(ClassName).newInstance();     }catch (Exception e) {       e.printStackTrace();     }     return f;   } } class hello{   public static void main(String[] a){     fruit f=Factory.getInstance("Reflect.Apple");     if(f!=null){       f.eat();     }   } }

現(xiàn)在就算我們添加任意多個子類的時候,工廠類就不需要修改。

上面的愛嗎雖然可以通過反射取得接口的實例,但是需要傳入完整的包和類名。而且用戶也無法知道一個接口有多少個可以使用的子類,所以我們通過屬性文件的形式配置所需要的子類。

下面我們來看看: 結(jié)合屬性文件的工廠模式

首先創(chuàng)建一個fruit.properties的資源文件,

內(nèi)容為:

apple=Reflect.Apple orange=Reflect.Orange

然后編寫主類代碼:

package Reflect;  import java.io.*; import java.util.*;  interface fruit{   public abstract void eat(); }  class Apple implements fruit{   public void eat(){     System.out.println("Apple");   } }  class Orange implements fruit{   public void eat(){     System.out.println("Orange");   } }  //操作屬性文件類 class init{   public static Properties getPro() throws FileNotFoundException, IOException{     Properties pro=new Properties();     File f=new File("fruit.properties");     if(f.exists()){       pro.load(new FileInputStream(f));     }else{       pro.setProperty("apple", "Reflect.Apple");       pro.setProperty("orange", "Reflect.Orange");       pro.store(new FileOutputStream(f), "FRUIT CLASS");     }     return pro;   } }  class Factory{   public static fruit getInstance(String ClassName){     fruit f=null;     try{       f=(fruit)Class.forName(ClassName).newInstance();     }catch (Exception e) {       e.printStackTrace();     }     return f;   } } class hello{   public static void main(String[] a) throws FileNotFoundException, IOException{     Properties pro=init.getPro();     fruit f=Factory.getInstance(pro.getProperty("apple"));     if(f!=null){       f.eat();     }   } }
【運行結(jié)果】:Apple

以上這篇java反射深入剖析(推薦)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 日照市| 冀州市| 缙云县| 金沙县| 八宿县| 桑日县| 竹山县| 轮台县| 乌拉特后旗| 海门市| 山阳县| 宁陵县| 昆明市| 岳阳县| 晴隆县| 嘉善县| 鞍山市| 台中市| 涿州市| 靖边县| 芒康县| 富裕县| 太保市| 澜沧| 信宜市| 鞍山市| 义乌市| 吉安市| 瑞安市| 通山县| 临邑县| 收藏| 五大连池市| 二手房| 吉安市| 绥棱县| 璧山县| 红原县| 常德市| 青浦区| 衡山县|