JAVA笔记【20131211】

一、反射

在运行时使用反射分析对象:

前面所述已经可以获取类中域的名称和类型,现在获取域的值,

使用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();


在实际执行代码tempF.get(e)时,由于类Employee中name域是private的,所以直接访问数据不合法,会抛出IllegalAccessException。

这是因为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[]可以被转换为对象,但不可以转换为对象数组。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值