首頁 >Java >java教程 >Java反射機制

Java反射機制

伊谢尔伦
伊谢尔伦原創
2017-01-16 11:58:121560瀏覽

當程式運行時,允許改變程式結構或變數類型,這種語言稱為動態語言。我們認為java並不是動態語言,但它有一個非常突出的動態相關機制,俗稱:反射。

IT產業裡這麼說,沒有反射也就沒有框架,現有的框架都是以反射為基礎。在實際專案開發中,用的最多的是框架,填的最多的是類,反射這個概念就是將框架和類揉在一起的調和劑。所以,反射才是接觸專案開發的敲門磚!

反射機制是什麼

反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態取得的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。


反射機制能做什麼

反射機制主要提供了以下功能: 

  • 在運作時判斷一個物件所屬的類;的物件;

  • 在運行時判斷任意一個類別所具有的成員變數和方法;

  • 在運行時呼叫任意一個物件的方法;

  • 產生動態代理。

  • 具體功能實現

1,反射機制獲取類別有三種方法,我們來獲取Employee類型

//第一种方式:  
Classc1 = Class.forName("Employee");  
//第二种方式:  
//java中每个类型都有class 属性.  
Classc2 = Employee.class;  
   
//第三种方式:  
//java语言中任何一个java对象都有getClass 方法  
Employeee = new Employee();  
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
  2,創建對象:獲取類以後我們來創建它的對象,利用newInstance:獲取類3,取得屬性:分為所有的屬性和指定的屬性:

 先看獲取所有的屬性的寫法:

Class c =Class.forName("Employee");  
  
//创建此Class 对象所表示的类的一个新实例  
Objecto = c.newInstance(); //调用了Employee的无参数构造方法.

獲取特定的屬性,對比著傳統的方法來學習:

//获取整个类  
            Class c = Class.forName("java.lang.Integer");  
              //获取所有的属性?  
            Field[] fs = c.getDeclaredFields();  
       
                   //定义可变长的字符串,用来存储属性  
            StringBuffer sb = new StringBuffer();  
            //通过追加的方法,将每个属性拼接到此字符串中  
            //最外边的public定义  
            sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");  
            //里边的每一个属性  
            for(Field field:fs){  
                sb.append("\t");//空格  
                sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等  
                sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字  
                sb.append(field.getName()+";\n");//属性的名字+回车  
            }  
      
            sb.append("}");  
      
            System.out.println(sb);

方法的反射

Class類別有一個最簡單的方法,getName():

public static void main(String[] args) throws Exception{  
              
<span style="white-space:pre">  </span>//以前的方式:  
    /* 
    User u = new User(); 
    u.age = 12; //set 
    System.out.println(u.age); //get 
    */  
              
    //获取类  
    Class c = Class.forName("User");  
    //获取id属性  
    Field idF = c.getDeclaredField("id");  
    //实例化这个类赋给o  
    Object o = c.newInstance();  
    //打破封装  
    idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  
    //给o对象的id属性赋值"110"  
    idF.set(o, "110"); //set  
    //get  
    System.out.println(idF.get(o));  
}
getName方法可以列印出該類別類型的類別名稱,我們也可以用getSimpleName()方法可以列印出不包含套件名稱的類別的名稱。從上面程式碼可以看出,基本的資料型別以及void關鍵字都是存在的類別類型。

案例:

public class Demo2 {
public static void main(String[] args) {
Class c1 = int.class;//int 的类类型
Class c2 = String.class;//String类的类类型
Class c3 = void.class;
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c2.getSimpleName());
System.out.println(c3.getName());
}
}

總結思路:

透過方法的反射得到該類別的名稱步驟:

1.取得該類別的類別類型

2.透過類別取得類別的方法(getMethods())

3.循環遍歷所取得的方法

4.透過這些方法的getReturnType()得到回傳值類型的類別類型,又透過該類別類型得到傳回值類型的名字

5.getName()得到方法的名稱,getParameterTypes()取得這個方法裡面的參數型別的類別類型。



成員變數的反射


首先我們需要認識到成員變數也是對象,是java.lang.reflect.Field類別的對象,那麼也就是說Field類別封裝了關於成員變數的操作。既然它封裝了成員變量,我們又該如何取得這些成員變數呢?它有這麼一個方法:

public class ClassUtil {
public static void printClassMethodMessage(Object obj){
//要获取类的信息》》首先我们要获取类的类类型
Class c = obj.getClass();
//我们知道Object类是一切类的父类,所以我们传递的是哪个子类的对象,c就是该子类的类类型。
//接下来我们要获取类的名称System.out.println("类的名称是:"+c.getName());
/*
*我们知道,万事万物都是对象,方法也是对象,是谁的对象呢?
* 在java里面,方法是Method类的对象
*一个成员方法就是一个Method的对象,那么Method就封装了对这个成员
*方法的操作
*///如果我们要获得所有的方法,可以用getMethods()方法,这个方法获取的是所有的Public的函数,包括父类继承而来的。如果我们要获取所有该类自己声明的方法,就可以用getDeclaredMethods()方法,这个方法是不问访问权限的。
Method[] ms = c.getMethods();//c.getDeclaredMethods()
//接下来我们拿到这些方法之后干什么?我们就可以获取这些方法的信息,比如方法的名字。
//首先我们要循环遍历这些方法
for(int i = 0; i < ms.length;i++){
//然后可以得到方法的返回值类型的类类型
Class returnType = ms[i].getReturnType();
//得到方法的返回值类型的名字
System.out.print(returnType.getName()+" ");
//得到方法的名称
System.out.print(ms[i].getName()+"(");
//获取参数类型--->得到的是参数列表的类型的类类型
Class[] paramTypes = ms[i].getParameterTypes();
for (Class class1 : paramTypes) {
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
}
這裡的getFields()方法所獲得的所有的public的成員變數的資訊。和方法的反射那裡public的成員變量,也有一個獲取所有自己聲明的成員變量的信息:
public class ClassUtil {
public static void printFieldMessage(Object obj){
Class c = obj.getClass();
//Field[] fs = c.getFields();
}

我們得到它之後,可以進行遍歷(既然封裝了Field的信息,那麼我們就可以得到Field類型)

Field[] fs = c.getDeclaredFields();

建構子的反射

不論是方法的反射、成員變數的反射、建構子的反射,我們只需要知道:要取得類別的信息,首先得取得類別的類別類型。

for (Field field : fs) {
//得到成员变量的类型的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成员变量的名称
String fieldName = field.getName();
System.out.println(typeName+" "+fieldName);
}

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn