Java程式中的各個Java類屬于同一類事物,描述這類事物的Java類名就是Class。
反射就是把Java類中的各種成分映射成相應的java類。例如,一個Java類中用一個Class類的對象來表示,一個類中的組成部分:成員變量,方法,構造方法,包等等資訊也用一個個的Java類來表示,就像汽車是一個類,汽車中的發動機,變速箱等等也是一個個的類。表示java類的Class類顯然要提供一系列的方法,來獲得其中的變量,方法,構造方法,修飾符,包等資訊,這些資訊就是用相應類的執行個體對象來表示,它們是Field、Method、Contructor、Package等等。
一個類中的每個成員都可以用相應的反射API類的一個執行個體對象來表示,通過調用Class類的方法可以得到這些執行個體對象後,得到這些執行個體對象後有什麼用呢?怎麼用呢?這正是學習和應用反射的要點。
對比提問:
衆多的人用一個什麼類表示?衆多的Java類用一個什麼類表示?
人 Person
Java類Class
對比提問:
Person類代表人,它的執行個體對象就是張三,李四這樣一個個具體的人,Class類代表Java類,它的各個執行個體對象又分别對應什麼呢?
對應各個類在記憶體中的位元組碼,例如,Person類的位元組碼,ArrayList類的位元組碼,等等。
一個類被類加載器加載到記憶體中,占用一片存儲空間,這個空間裡面的内容就是類的位元組碼,不同的類的位元組碼是不同的,
是以它們在記憶體中的内容是不同的,這一個個的空間可分别用一個個的對象來表示,這些對象顯然具有相同的類型,這個類型是什麼呢?
如何得到各個位元組碼對應的執行個體對象( Class類型)
三種方式:
1.
類名.class,例如,System.class
2.
對象.getClass(),例如,new Date().getClass()
3.
Class.forName("類名"),例如,Class.forName("java.util.Date");
下面是執行個體用到的一個類:
public class Person
{
private int id;
private String name;
public Person(int i,String n)
{
id=i;
name=n;
}
@Override
public String toString()
{
return name+"="+id;
}
}
下面是示範執行個體與注釋:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class ReflectDemo
{
public static void main(String[] args)
throws Exception
{
test4();
test3();
ReflectDemo.test2();
ReflectDemo.test1();
}
//在String泛型修飾的集合内放入Integer對象
public static void test4() throws Exception
{
List<String> list=new ArrayList<String>();
list.add("strlist");
System.out.println("==============="+list.size());
Class<Object> cla=(Class<Object>) Class.forName("java.util.List");
Method met=cla.getMethod("add", Object.class);
met.invoke(list, new Integer(1));
System.out.println("==============="+list.size());
for (int i=0;i<list.size();i++)
{
System.out.println(String.valueOf(list.get(i)));
}
System.out.println("==============="+list.size());
}
//把對象的屬性值改變
public static void test3() throws Exception
{
Person per=new Person(112,"aAAGGGasdJHdzdanacca");
System.out.println(per);
//擷取類的位元組碼對象
Class cla=Class.forName("ljt.reflect.Person");
//擷取此對象的所有字段
Field[] fileds=cla.getDeclaredFields();
for (Field field : fileds)
{
field.setAccessible(true);
//如果此字段是String類型的話
if(field.getType()==String.class)
{
//擷取此字段的内容
String oldField=(String)field.get(per);
//将字段中的小寫字母全部轉換為大寫字母
char[] oldChar=oldField.toCharArray();
for (int i=0;i<oldChar.length;i++)
{
if(oldChar[i]>96)
{
oldChar[i]=(char)(oldChar[i]-32);
}
}
String newField=new String(oldChar);
//将對象的相應字段值改變
field.set(per, newField);
}
}
System.out.println(per);
}
//反射的三種方式
public static void test1()
throws ClassNotFoundException
{
/*
* 得到各個位元組碼對應的執行個體對象( Class類型)
三種方式:
1.
類名.class,例如,System.class
2.
對象.getClass(),例如,new Date().getClass()
3.
Class.forName("類名"),例如,Class.forName("java.util.Date");*/
//類名.class,例如,System.class
Class<String> c1=String.class;
//對象.getClass(),例如,new Date().getClass()
Class<String> c2=(Class<String>)new String().getClass();
//Class.forName("類名"),例如,Class.forName("java.util.Date")
Class<String> c3=(Class<String>)Class.forName("java.lang.String");
System.out.println((c1==c2)+"--"+(c1==c3));
}
//利用反射擷取構造器
public static void test2()
throws
NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
/*
* Class 類的執行個體表示正在運作的 Java 應用程式中的類和接口。
* 方法:
* Constructor<T> getConstructor(Class<?>... parameterTypes)
傳回一個 Constructor 對象,它反映此 Class 對象所表示的類的指定公共構造方法。
Constructor<?>[] getConstructors()
傳回一個包含某些 Constructor 對象的數組,這些對象反映此 Class 對象所表示的類的所有公共構造方法。
java.lang.reflect 類 Constructor<T>
Constructor 提供關于類的單個構造方法的資訊以及對它的通路權限。
方法:
T newInstance(Object... initargs)
使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新執行個體,并用指定的初始化參數初始化該執行個體。
* */
Class<String> c1=String.class;
//擷取參數清單為一個String類型的對象的構造方法
Constructor<String> const1=c1.getConstructor(String.class);
//通過Constructor的newInstance方法擷取String的對象
String str=const1.newInstance("ijava");
System.out.println(str);
//無參構造可以直接使用位元組碼對象建立該類的執行個體
String str2=c1.newInstance();
str2="ljt";
System.out.println(str2);
}
}