什麼是反射:
反射是Java語言的一個特性,它允許程序在運行時來進行自我檢查並且對內部的成員進行操作。例如它允許一個java的類獲取他所有的成員變量和方法並且顯示出來。
java的反射機制的實現要藉助4個類:Class,Constructor,Field,Method 其中Class代表的是類對象,Constructor 類的構造器對象,Field 類的屬性對象,Method
類的方法對象。通過這四個對象我們可以粗略的看到一個類的各個組成部分。
在正常情況下,必須知道一個類的完整路徑之後纔可以實例化對象,但是在java中也允許通過一個對象來找到其所在的類的信息,那麼這實際上就是Class類的功能。
-
package com.itmyhome;
-
-
class A{
-
-
}
-
public class T {
-
-
public static void main(String[] args) {
-
-
A a = new A();
-
System.out.println(a.getClass().getName());
-
}
-
-
}
Object類的支持
在Object類中定義了以下的方法,此方法將被所有子類繼承:
public final Class getClass()
以上的方法返回值的類型是一個"Class"類,實際上此類是java反射的源頭,實際上所謂反射從程序的運行結果來看也很好理解,即:可以通過對象反射求出類的名稱。
Class類
Class本身表示一個類的本身,通過Class可以完整的得到一個類中的完整結構,包括此類中的方法定義,屬性定義等。
實例化Class類對象
有三種方法實例化Class對象:
第一種:通過forName()方法
第二種:類.class
第三種:對象.getClass()
-
package com.itmyhome;
-
-
class A{
-
-
}
-
public class T {
-
-
public static void main(String[] args) throws ClassNotFoundException {
-
-
Class<?> c1 = Class.forName("com.itmyhome.A");
-
Class<?> c2 = A.class;
-
Class<?> c3 = new A().getClass();
-
System.out.println(c1.getName());
-
System.out.println(c2.getName());
-
System.out.println(c3.getName());
-
}
-
-
}
Class主要是反射的源頭,不光可以取得對象所在類的信息,也可以直接通過Class類的方法進行對象的實例化操作正常情況下,使用關鍵字new爲對象實例化,如果現在已經實例化好了Class對象,則就可以通過Class類中提供的
實例化對象
-
package com.itmyhome;
-
-
class Person {
-
private String name;
-
private int age;
-
-
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 String toString() {
-
-
return "name: " + name + ",age: " + age;
-
}
-
}
-
-
public class T {
-
-
public static void main(String[] args) throws ClassNotFoundException {
-
Class<?> c = Class.forName("com.itmyhome.Person");
-
Person person = null;
-
try {
-
person = (Person) c.newInstance();
-
} catch (InstantiationException e) {
-
e.printStackTrace();
-
} catch (IllegalAccessException e) {
-
e.printStackTrace();
-
}
-
person.setName("itmyhome");
-
person.setAge(23);
-
System.out.println(person);
-
}
-
-
}
通過以上的代碼,可以發現,即使不使用關鍵字new對象也可以進行實例化操作,反射的作用。
但是,在使用以上操作的時候有一點必須注意,在操作中類中必須存在無參構造方法,否則無法實例化
報以下異常
-
java.lang.InstantiationException: com.itmyhome.Person
-
at java.lang.Class.newInstance0(Class.java:340)
-
at java.lang.Class.newInstance(Class.java:308)
-
at com.itmyhome.T.main(T.java:35)
-
Exception in thread "main" java.lang.NullPointerException
-
at com.itmyhome.T.main(T.java:41)
對於以上的程序也並非沒有解決的方法,也是可以通過其他的方式進行實例化操作的,只是在操作的時候需要明確的調用類中的構造方法,並將參數傳遞進去之後纔可以進行實例化操作,操作步驟如下:
1、通過Class類中的getConstructors()取得本類中的全部構造方法。
2、向構造方法中傳遞一個對象數組進去,裏面包含了構造方法中所需的各個參數。
3、之後通過Constructor實例化對象。
-
package com.itmyhome;
-
-
import java.lang.reflect.Constructor;
-
-
class Person {
-
private String name;
-
private int age;
-
-
public Person(String name,int age){
-
this.name = name;
-
this.age = age;
-
}
-
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 String toString() {
-
-
return "name: " + name + ",age: " + age;
-
}
-
}
-
-
public class T {
-
-
public static void main(String[] args) throws ClassNotFoundException{
-
Class<?> c = Class.forName("com.itmyhome.Person");
-
Constructor<?> cons[] = c.getConstructors();
-
Person person = null;
-
try {
-
person = (Person) cons[0].newInstance("itmyhome",23);
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
person.setName("itmyhome");
-
person.setAge(23);
-
System.out.println(person);
-
}
-
-
}
反射機制的深入----取得類的結構
在實際開發中,以上的程序就是反射應用最多的地方,當然,反射機制所提供的功能遠不止如此,還可以通過反射得到一個類的完整結構,那麼這就要使用到java.lang.reflect包中的以下幾個類:
Constructor:表示類中的構造方法
Field:表示類中的屬性
Method:表示類中的方法
這三個類都是AccessibleObject類中的子類
-
package com.itmyhome;
-
-
interface IPerson{
-
public static final String NAME = "itmyhome";
-
public String toSay();
-
public String toEat(String name,int age);
-
}
-
class Person implements IPerson{
-
private String name;
-
private int age;
-
public Person(){
-
-
}
-
public Person(String name,int age){
-
this.name = name;
-
this.age = age;
-
}
-
@Override
-
public String toSay() {
-
return "hello!";
-
}
-
-
@Override
-
public String toEat(String name, int age) {
-
return "name: "+name+",age: "+age;
-
}
-
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;
-
}
-
}
取得類所實現的全部接口
要想取得一個類所實現的全部接口,則必須使用Class類中的getInterfaces()方法,此方法定義如下:
-
public Class[] getInterfaces()
此方法返回一個Class類的對象數組,之後就可以直接利用Class類中的getName()方法輸出即可。
因爲一個類可以同時實現多個接口,所以在此處就以一個數組的形式返回實現的全部接口。
-
public class T {
-
public static void main(String[] args) throws Exception{
-
Class<?> cl = Class.forName("com.itmyhome.Person");
-
Class<?> c[] = cl.getInterfaces();
-
for (int i = 0; i < c.length; i++) {
-
System.out.println(c[i].getName());
-
}
-
}
-
}
取得類所繼承的父類
一個類可以實現多個接口,但是隻能繼承一個父類,所以如果要想取得一個類的父類,可以直接使用Class類中的getSuperClass()方法。此方法定義如下:
-
public Class<? super T> getSuperClass()
此方法返回的是Class實例,和之前的得到接口一樣,可以通過getName()方法取得名次。
一個類只繼承一個父類,如果一個類中沒有明確的指明繼承哪個類,則肯定繼承的是Object類。
-
public class T {
-
public static void main(String[] args) throws Exception{
-
Class<?> cl = Class.forName("com.itmyhome.Person");
-
Class<?> c = cl.getSuperclass();
-
System.out.println(c.getName());
-
}
-
}
取得類中的全部構造方法
-
public class T {
-
public static void main(String[] args) throws Exception{
-
Class<?> cl = Class.forName("com.itmyhome.Person");
-
Constructor<?> c[] = cl.getConstructors();
-
for (int i = 0; i < c.length; i++) {
-
System.out.println(c[i]);
-
}
-
}
-
}
取得類中的方法
要想取得一個類中的全部方法,可以使用Class類中的getDeclaredMethods()方法,此方法返回一個Method類的對象數組,而如果要想進一步取得方法的具體信息,例如:方法的參數,拋出的異常等等,則就必須依靠Method類
public Method[] getDeclaredMethods() 輸出本類中的全部方法
public Method[] getMethods() 輸出全部的方法
-
public class T {
-
public static void main(String[] args) throws Exception{
-
Class<?> cl = Class.forName("com.itmyhome.Person");
-
Method m1[] = cl.getMethods();
-
for (int i = 0; i < m1.length; i++) {
-
System.out.println(m1[i]);
-
}
-
System.out.println("*************");
-
Method m2[] = cl.getDeclaredMethods();
-
for (int i = 0; i < m2.length; i++) {
-
System.out.println(m2[i]);
-
}
-
}
-
}
取得類中的屬性
public Field[] getFields() 得到實現的接口和父類中的公共屬性
public Field[] getDeclaredFields() 得到本類中的全部屬性
以上方法返回的都是Field的數組,每一個Field對象就表示類中的一個屬性
-
public class T {
-
public static void main(String[] args) throws Exception{
-
Class<?> cl = Class.forName("com.itmyhome.Person");
-
Field f1[] = cl.getFields();
-
for (int i = 0; i < f1.length; i++) {
-
System.out.println(f1[i]);
-
}
-
System.out.println("*********");
-
Field f2[] = cl.getDeclaredFields();
-
for (int i = 0; i < f2.length; i++) {
-
System.out.println(f2[i]);
-
}
-
}
-
}
轉載出處: http://blog.csdn.net/itmyhome1990/article/details/8946220