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[]可以被轉換爲對象,但不可以轉換爲對象數組。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章