Java基礎(四):java 反射機制

反射是什麼

JAVA反射機制是在運行狀態中,對於任意一個類,都可以獲取這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取類信息以及動態調用對象內容就稱爲java語言的反射機制。【翻譯於 官方文檔】html

反射的做用

  • 在運行時判斷任意一個對象所屬的類;
  • 在運行時構造任意一個類的對象;
  • 在運行時判斷任意一個類所具備的成員變量和方法;
  • 在運行時調用任意一個對象的方法;

new和反射建立的區別

從結果來講沒有區別。java

new:靜態編譯,只能用於編譯期就能肯定的類型,並且須要import相應的包。數組

反射:動態編譯,在運行時能夠肯定類型並建立其對象,可以實現一些更爲動態的效果。bash

反射的實現

咱們知道,要使用一個類,就要先把它加載到虛擬機中,生成一個Class對象。這個class對象就保存了這個類的一切信息。 反射機制的實現,就是獲取這個Class對象,經過Class對象去訪問類、對象的元數據以及運行時的數據。有三種方法得到類的Class對象:spa

  • Class.forName(String className)
  • className.class
  • 實例對象.getClass()

什麼是class類

在面向對象的世界裏,萬物皆對象。類是對象,類是java.lang.Class類的實例對象。另外class類只有java虛擬機才能new出來,任何一個類都是Class 類的實例對象,這實例對象有三種表達方式:翻譯

public class Person {
}
複製代碼
public class PersonClassTest {
    public static void main(String[] args) {
        try {
            Person p = new Person();
            //方式1
            Class p1 = Person.class;
            //方式2
            Class p2 = p.getClass();
            //方式3
            Class p3 = Class.forName("com.java.xiaoxin.Person");
            //能夠經過類的類型建立該類的實例對象
            Person person = (Person) p1.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
複製代碼

反射涉及的API

反射首先獲取Class對象;而後獲取Method類和Field類;最後經過Method和Field類進行具體的方法調用或屬性訪問。code

1.在運行時獲取對象所屬類的類名等信息
對象名.getClass().getName();
複製代碼
public class PersonClassTest {
    public static void main(String[] args) {
        String name = Person.class.getName();
        System.out.println(name);//com.java.xiaoxin.Person
    }
}
複製代碼
2.在運行時,經過建立class對象,獲取本身的父類信息
Class<?> clazz = Class.forName(當前類);
 Class<?> parentClass = clazz.getSuperclass();
 parentClass.getName();//得到父類名
複製代碼
public class PersonClassTest {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("com.java.xiaoxin.Person");
            Class<?> parentClass = clazz.getSuperclass();
            parentClass.getName();
            System.out.println(parentClass.getName());//java.lang.Object
        }catch (Exception e){
			e.printStackTrace();
        }
    }
}
複製代碼
3.經過反射機制建立一個類的對象
1:反射建立class對象
2:Classname 對象=classname.newInstance(參數);
複製代碼
public class PersonClassTest {
    public static void main(String[] args) {
        try {
           Class clazz = Class.forName("com.java.xiaoxin.Person");
           Person person = (Person) clazz.newInstance();
        }catch (Exception e){
			e.printStackTrace();
        }
    }
}
複製代碼
4.獲取類的所有方法,存於一個數組中
//建立class對象
Class<?> clazz = Class.forName(ClassName);
// 返回聲明的全部方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。 
Method[] method1 = clazz.getDeclaredMethods();
//返回可被訪問的公共方法 
Method[] method2 = clazz.getMethods();
複製代碼
public class PersonClassTest {

    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("com.java.xiaoxin.Person");
            /** * 一個成員方法就是一個method對象 * getMethod()全部的 public方法,包括父類繼承的 public * getDeclaredMethods()獲取該類全部的方法,包括private ,但不包括繼承的方法。 */
            Method[] methods = clazz.getMethods();//獲取方法
            //獲取因此的方法,包括private ,c.getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                //獲得方法的返回類型
                Class returnType = methods[i].getReturnType();
                System.out.print(returnType.getName());
                //獲得方法名:
                System.out.print(methods[i].getName() + "(");

                Class[] parameterTypes = methods[i].getParameterTypes();
                for (Class class1 : parameterTypes) {
                    System.out.print(class1.getName() + ",");
                }
                System.out.println(")");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
複製代碼

輸出:htm

voidwait()
voidwait(long,int,)
voidwait(long,)
booleanequals(java.lang.Object,)
java.lang.StringtoString()
inthashCode()
java.lang.ClassgetClass()
voidnotify()
voidnotifyAll()
複製代碼
5.獲取類的所有字段,存於一個數組中
Class<?> clazz = Class.forName(classname);
// 取得本類已聲明的全部字段,包括私有的、保護的
Field[] field = clazz.getDeclaredFields();
// 取得本類中可訪問的全部公共字段
Field[] filed1 = clazz.getFields();
複製代碼
public class Person {
   private String name;
   public int age;
}
複製代碼
public class PersonClassTest {

    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("com.java.xiaoxin.Person");
            Field[] field = clazz.getDeclaredFields();
            Field[] filed1 = clazz.getFields();
            for(Field f:field){
                //獲取成員變量的類型
                Class filedType=f.getType();
                System.out.println(filedType.getName()+"-->"+f.getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
複製代碼

輸出:對象

java.lang.String-->name
int-->age
複製代碼
6.方法反射的操做

獲取一個方法:須要獲取方法的名稱和方法的參數才能決定一個方法。blog

方法的反射操做:

method.invoke(對象,參數列表);
複製代碼
public class Person {
    private String name;
    public int age;

    public void say(String name,int age){
        System.out.print(name+"今年"+age+"歲");
    }

}
複製代碼
public class PersonClassTest {

    public static void main(String[] args) {
        try {
            Person person=new Person();
            Class clazz=person.getClass();
            Method method=clazz.getMethod("say",new Class[]{String.class,int.class});
            //也能夠 Method method=c.getMethod("add",String.class,int.class);
            //方法的反射操做
            method.invoke(person,"小新",18);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
複製代碼

輸出:

小新今年18歲
複製代碼

參考資料

www.cnblogs.com/huangdabing…

www.fangzhipeng.com/javaintervi…

相關文章
相關標籤/搜索