專用通道>

您當前所在位置: 首頁 > 行業新聞 > IT技術討論 >

IT技術討論

Java反射

發布者:亚游成都錦江點擊: 分享到
在Java運行時環境中,對於任意一個類能否知道這個類有哪些屬性和方法?對於任意一個對象,能否調用它的任意一個方法?答案是肯定的。這種動態獲取類的信息以及動態調用對象的方

在Java運行時環境中,對於任意一個類能否知道這個類有哪些屬性和方法?對於任意一個對象,能否調用它的任意一個方法?答案是肯定的。這種動態獲取類的信息以及動態調用對象的方法的功能來自於Java語言的反射機製(Reflection)。
申請免費試學】【在線報名在線谘詢

Java反射機製主要提供一下功能。

在運行時判斷任意一個對象所屬的類。

在運行時構造任意一個類的對象。

在運行時判斷任意一個類所具有的成員變量和方法。

在運行時調用任意一個對象的方法。

Reflection是Java被視為動態(或準動態)語言的一個關鍵性質。這個機製允許程序在運行時透過Reflection API取得任何一個已知名稱的class的內部信息,包括其modifiers(諸如piblic,static等等)、superclass(例如Object)、實現之interfaces(例如Serializable),也包括fields和methods的所有信息,並可於運行時改變fields內容或調用methods。
申請免費試學】【在線報名在線谘詢

一般而言,開發者社群說到動態語言,大致認同的一個定義是:“程序運行時,允許改變程序結構或變量類型,這種語言稱為動態語言”。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言。

盡管在這樣的定義與分類下Java不是動態語言,它卻有著一個非常突出的動態相關機製:Reflection。這個字的意思是:“反射、映像、倒影”,用在Java身上指的是亚游可以於運行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。這種“看透class的能力(the ability of the program to examine itself)”被稱為introspection(內省、內觀、反省)。Reflection和introspection是常被並提的兩個術語。
申請免費試學】【在線報名在線谘詢

在JDK中,主要由以下類來實現Java反射機製,這些類位於java.lang.reflect包中。

Class類:代表一個類。

File類:代表類的成員變量(成員變量也成為類的屬性)

Method類:代表類的方法。

Construtor類:代表類的構造方法

Arry類:提供了動態創建數組,以及訪問數組的元素的靜態方法。

Class Class<T>Java當中每一個對象都會有一個與之關聯的class對象,這個class對象是唯一的。這個class對象是在JDK啟動的時候就加載進來的,那麽他是亚游反射的入口點。
申請免費試學】【在線報名在線谘詢

newInstance()

Creates a new instance of the class represented by this Class object.

創建一個新的實例,是由這個Class對象所代表的那個類的實例

Class Method:對於我在類中定義的任意一個方法都會有一個與之關聯的Method對象,這個Method會獲得這個方法的所有信息,除了方法定義之外,其他都能獲得。

Java的每一個類他裏麵的每一個方法都會有一個與之對應的Method對象,如果要想通過反射來調用這個方法的時候,你就要獲得這個方法與之對應的Method對象,獲得Method對象之後,就能通過Method對象所代表的那個方法。

getMethod(String name, Class<?>... parameterTypes)方法

想獲取一個方法通過這個方法的名字和方法的參數(因為有重載所以才要參數)

invoke(Object obj, Object... args)

返回一個Object類型,其實就是方法的返回類型(引用(int--integer))
申請免費試學】【在線報名在線谘詢

代碼實例

package com.test;

import java.lang.reflect.Method;

public class InvokeTester {

public int add(int param1, int param2) {

return param1 + param2;

}

public String echo(String msg) {

return "hello:" + msg;

}

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

Class<?> classType = InvokeTester.class;

  // 獲得InvokeTester類所對應的Class對象

Object invokeTester = classType.newInstance();

// 以上兩行代碼等價於

// InvokeTester it = new InvokeTester();

Method addMethod = classType.getMethod("add", int.class, int.class);

// 這個Method對象就等價於add方法

Object result = addMethod.invoke(invokeTester, new Object[]{100,200});

//以上兩行代碼等價於it.add(100,200);

System.out.println((Integer) result);

Method echoMethod = classType.getMethod("echo",

new Class[] { String.class });

//以上兩行代碼等價於it.echo("hello");

Object result2 = echoMethod.invoke(invokeTester, new Object[]{"hello"});

System.out.println((String)result2);

}

}

getConstructor(Class<?>... parameterTypes)

獲得某個特定的構造方法所對應的對象,在通過構造方法Constructor的newInstance(Object... initargs)方法生成類的實例
申請免費試學】【在線報名在線谘詢

getDeclaredFields()獲得對象的所有屬性,每個屬性對應一個Field對象

實例2package com.test;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

public class ReflectTester {

public Object copy(Object object) throws Exception {

Class<?> classType = object.getClass();

System.out.println("Class:" + classType.getName());

// 通過默認構造方法創建一個新的對象

Object objectCopy = classType.getConstructor(new Class[] {})

.newInstance(new Object[] {});

// 上麵這行代碼等價於Object objectCopy2 = classType.newInstance();這個是唯一的,

// 使用默認的構造方法,而這裏使用的則是萬能的,能通過不同的構造方法實例對象

// 而且getConstructor方法和newInstance方法的參數個數和類型一定要匹配

// 先是構造方法的參數類型,然後是實例對象為構造方法傳的真實參數

// 獲得對象的所有屬性

Field fields[] = classType.getDeclaredFields();

for (int i = 0; i < fields.length; i++) {

Field field = fields[i];

String fieldName = field.getName();

String firstLetter = fieldName.substring(0, 1).toUpperCase();

// 獲得和屬性對應的getXXX()方法的名字

String getMethodName = "get" + firstLetter + fieldName.substring(1);

// 獲得和屬性對應的setXXX()方法的名字

String setMethodName = "set" + firstLetter + fieldName.substring(1);

// 獲得和屬性對應的getXXX()方法

Method getMethod = classType.getMethod(getMethodName,

new Class[] {});

// 獲得和屬性對應的setXXX()方法

Method setMethod = classType.getMethod(setMethodName,

new Class[] { field.getType() });

// 調用原對象的getXXX()方法

Object value = getMethod.invoke(object, new Object[] {});

System.out.println(fieldName + ":" + value);

// 調用拷貝對象的setXXX()方法

setMethod.invoke(objectCopy, new Object[] { value });

}

return objectCopy;

}

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

Customer customer = new Customer("Tom", 21);

customer.setId(new Long(1));

Customer customerCopy = (Customer) new ReflectTester().copy(customer);

System.out.println("Copy information:" + customerCopy.getId() + " "

+ customerCopy.getName() + " " + customerCopy.getAge());

}

}

class Customer {

private Long id;

private String name;

private int age;

public Customer() {

}

public Customer(String name, int age) {

this.name = name;

this.age = age;

}

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

通過反射操作一維數組

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

{

Class classType = Class.forName("java.lang.String");

// 創建一個長度為10的字符串數組

Object array = Array.newInstance(classType, 10);

// 把索引位置為5的元素設為"hello"

Array.set(array, 5, "hello");

// 獲得索引位置為5的元素的值

String s = (String) Array.get(array, 5);

System.out.println(s);

}

Class class十分特殊,他和一般的classes一樣繼承自Object,其實體用以表達Java程序運行時的classes和interfaces,也用來表達enum、array、primitive、Java types

(boolean,byte,char,short,int,long,float,double)以及關鍵詞void。當一個class被加載,或當加載器(class loader)的defineClass()被JVM調用,JVM便自定產生一個Class object。如果你想借由“修改Java標準庫源碼”來觀察Class object的實際生成時機(例如在Class的constructor內添加一個println(),不能夠!因為Class並沒有public constructor)

Class是Reflection起源。針對任何你想探勘的class,唯有先為他產生一個cClass object,接下來才能經由後者喚起為數十多個的Reflection APIS。
申請免費試學】【在線報名在線谘詢



亚游谘詢老師

成都優越教育谘詢有限公司(亚游成都錦江校區介紹)

成都優越教育谘詢有限公司(亚游成都錦江校區)是亚游總部在成都設立的一家示範校區。涵蓋ACCP、Java、.Net、網絡營銷、市場營銷,遊戲開發等多專業校區,承擔教學、就業示範、以及教師培養輸送等職責。
亚游作為北京大學下屬的專業計算機學校,以北京大學強大師資作為依托,連續13年被評為“中國IT教育第一品牌”,累計培養60+萬優秀軟件工程師,是名符其實的軟件工程師的搖籃……請認準品牌名校——亚游成都錦江校區,地址:成都市春熙路北口東行500米(大慈寺22號)。