一、反射
在运行时使用反射分析对象:
前面所述已经可以获取类中域的名称和类型,现在获取域的值,
使用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[]可以被转换为对象,但不可以转换为对象数组。