一、反射
在運行時使用反射分析對象:
前面所述已經可以獲取類中域的名稱和類型,現在獲取域的值,
使用Field類中的get方法,該方法返回的是一個Object對象,對象的值即爲當前域的值。
注:對於基本類型數據,由於不是類,所以返回時會自動打包爲基本數據類型對應的類對象,當然也可以使用Field類中的getInt、getDouble等方法直接返回基本類型數據。
Employee e = new Employee("zhangs",100);
Class tempC = e.getClass();
Field tempF = tempC.getDeclaredField("name");
String tempS = tempF.get(e).toString();
這是因爲Java的安全機制只允許查看任意對象有哪些域,而不允許讀取其值。
也即反射機制的默認行爲受限於Java的訪問控制。
當然,如果一個Java應用程序沒有收到安全管理器的控制,就可以覆蓋訪問控制。
通過調用AccessibleObject類的setAccessible方法,設置標誌flag爲true即可。AccessibleObject類是Field、Method、Constructor類的父類。
有訪問域的方法,自然也就有設置域的方法,對應的方法爲set(Object obj,Object value)。
import java.lang.reflect.*;
public class Test25
{
public static void main(String[] args)
{
Employee staff = new Employee("zhangs",24);
Class tempC = staff.getClass();
try
{
Field tempF = tempC.getDeclaredField("name");
tempF.setAccessible(true);
String tempS = tempF.get(staff).toString();
System.out.println(tempS);
}
catch(IllegalAccessException e)
{
e.printStackTrace();
}
catch(NoSuchFieldException e)
{
e.printStackTrace();
}
System.exit(0);
}
}
class Employee
{
public Employee(String name,int id)
{
this.name = name;
this.id = id;
nextId++;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public float getSalary()
{
return salary;
}
public void setSalary(float salary)
{
this.salary = salary;
}
public static int getNextId()
{
return nextId ;
}
private String name;
private int id;
private static int nextId = 0;
private float salary ;
}
使用反射編寫通用的toString方法:
import java.lang.reflect.*;
import java.util.*;
public class Test26
{
public static void main(String[] args)
{
int[] sz ={1,3,5,7,6,9,8};
System.out.println(new ObjectAnalize().toString(sz));
ArrayList<Integer> al = new ArrayList<Integer>();
for(int i=0;i<=5;i++)
{
al.add(i,i*i);
}
al.trimToSize();
System.out.println(new ObjectAnalize().toString(al));
}
}
class ObjectAnalize
{
public String toString(Object obj)
{
if(obj==null)
return "null";
if(visited.contains(obj))
return "...";
visited.add(obj);
Class tempC = obj.getClass();
if(tempC==String.class)
return (String)obj;
if(tempC.isArray())
{
String tempA = tempC.getComponentType()+"[]{";
for(int i=0;i<Array.getLength(obj);i++)
{
if(i>0)
tempA += ",";
Object val = Array.get(obj,i);
if(tempC.getComponentType().isPrimitive())
{
tempA += val;
}
else
{
tempA += toString(val);
}
}
return tempA+"}";
}
String tempA = tempC.getName();
do
{
tempA += "[";
Field[] field = tempC.getDeclaredFields();
AccessibleObject.setAccessible(field,true);
for(Field f:field)
{
if(!Modifier.isStatic(f.getModifiers()))
{
if(!tempA.endsWith("["))
tempA += ",";
tempA += f.getName()+"=";
try
{
Class t = f.getType();
Object val = f.get(obj);
if(t.isPrimitive())
{
tempA += val;
}
else
{
tempA += toString(val);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
tempA += "]";
tempC = tempC.getSuperclass();
}
while(tempC != null);
return tempA;
}
private ArrayList<Object> visited = new ArrayList<Object>();
}
可以使用通用的toString方法實現自己類中的toString方法
public String toString()
{
return new ObjectAnalize().toString(this);
}
使用反射編寫通用的數組代碼:
動態擴展數組,java.lang.reflect包中的Array類允許動態的創建數組。
static Object arrayGrow(Object tp)
{
Class tc = tp.getClass();
if(!tc.isArray())
return null;
Class componentType = tc.getComponentType();
int l = Array.getLength(tp);
int nl = l*11/10+10;
Object newArray = Array.newInstance(componentType,nl);
System.arraycopy(tp,0,newArray,0,l);
return newArray;
}
關於參數設置爲Object而不是Object[],是因爲int[]可以被轉換爲對象,但不可以轉換爲對象數組。