java反射学习札记

java反射学习笔记
    浑浑噩噩毕业半年多,对于以前学的逻辑的知识也忘记的差不多了,看来是没有希望回去做逻辑了.只能继续自己的码农之路.啥都不懂,但是还是写点东西权当自己的笔记吧.
    最近自己在看spring框架,虽然对于spring的了解完全是菜鸟级,但是还是看到了点java的反射的应用.之前对于反射一知半解,决定自己写几个test学习下.
    关于原理什么的完全不知道,以后有时间在去深究吧,毕竟对于我这种菜鸟来说先学点来用就可以混下了.那么高深的要积累才能看的吧.
    对于一个正在运行的程序,如果能够了解到他其中的类属性以及域属性那是多好美妙的事情.java的反射就是实现这个.
这里主要有3个类:

TaskStarter定时执行任务
package com.maximilian.www;

import java.util.Timer;

public class TaskStarter 
{
	private static final long delayTime=1000;
	private static final long intervalTime=2000;
	private static Timer timer = new Timer();
	public static void main(String [] args)
	{
		System.out.println("start task!");
		timer.schedule(new IntervalTask(), delayTime, intervalTime);
	}
}


IntervalTask:任务
package com.maximilian.www;

import java.util.TimerTask;
import test.ReflectionTest;

public class IntervalTask extends TimerTask
{
	public int tmpInt=0;
	public String tmpString="0";
	
	private String string1 = "1";
	private static String string2 = "2";
	public String string3 = "3";
	public static String string4 = "4";
	public IntervalTask(int argInt,String argString)
	{
		this.tmpInt=argInt;
		this.tmpString=argString;
	}
	
	@Override
    public void run()
    {
	    System.out.println("----------------"); 
	    ReflectionTest test = new ReflectionTest();
	    System.out.println(test.getObjectProperty(this, "string3"));
	    Object[] args ={1,"1"};
	    test.getAndInvokeMethod(this, null, "print1");
	    test.getAndInvokeMethod(this, args, "print5");
	    
    }
	private void print1()
	{
		System.out.println("string1:"+string1+"\r\n"+"string2:"+string2+"\r\n"+"string3:"+string3+"\r\n"+"string4:"+string4+"\r\n");
	}
	private static void print2()
	{
		System.out.println("string2:"+string2+"\r\n"+"string4:"+string4+"\r\n");
	}
	public void print3()
	{
		System.out.println("string1:"+string1+"\r\n"+"string2:"+string2+"\r\n"+"string3:"+string3+"\r\n"+"string4:"+string4+"\r\n");
	}
	public static void print4()
	{
		System.out.println("string2:"+string2+"\r\n"+"string4:"+string4+"\r\n");
	}
	public static void print5(int argInt, String argString)
	{
		System.out.println("string2:"+string2+"\r\n"+"string4:"+string4+"\r\n");
	}
	public  void print6(int argInt, String argString)
	{
		System.out.println("string2:"+string2+"\r\n"+"string4:"+string4+"\r\n");
	}
}


ReflectionTest:测试反射

主要可以做到的就是下面:

1. 新建某个类的实例

	    Class<?> taskClass = Class.forName("com.maximilian.www.IntervalTask");
	    Constructor<?> con = taskClass.getConstructor(new Class[]{});
	    Object obj1 = con.newInstance();
	    System.out.println(obj1.toString());
	    System.out.println("tmpInt:"+((IntervalTask)obj1).tmpInt+"  tmpString:"+((IntervalTask)obj1).tmpString);


打印结果: com.maximilian.www.IntervalTask@12940b3
tmpInt:0  tmpString:0
上面是类的不带参的构造函数,当然也可以调用带参数的不同的构造函数.
如果: IntervalTask的构造函数有public IntervalTask(int argInt,String argString),那么可以通过下面新建实例:

	    Class<?> [] parameterTypes = {int.class,String.class};
	    Constructor<?> con2 = taskClass.getConstructor(parameterTypes);
	    Object [] paramters ={1,"1"};
	    Object obj2 = con2.newInstance(paramters);
	    System.out.println(obj2.toString());
	    System.out.println("tmpInt:"+((IntervalTask)obj2).tmpInt+"  tmpString:"+((IntervalTask)obj2).tmpString);


打印结果: com.maximilian.www.IntervalTask@158f9d3
tmpInt:1  tmpString:1

2. 获取某个类的静态属性

	    Field field =taskClass.getField("string4");
Object value = field.get(taskClass);
	    System.out.println(value);


这里的有另外一个方法getDeclaredField与getField区别就是前面可以获取类的私有属性.
当不清楚属性的名称时可以获取一次获取全部的
    Field [] field =taskClass. getDeclaredFields();
对于类中域不知道类型可以通过:
    Field field =taskClass.getField("string4");
    Class<?> typeClass = field.getType();
    做修改的话如下(这里的修改对于运行的程序没有作用,可以通过传入运行程序的类对象在这里做修改):

field.setAccessible(true);
Constructor<?> constructor = typeClass.getConstructor(String.class);
	    Object object = constructor.newInstance("11");
	    field.set(taskClass,object);
	    Object value = field.get(taskClass);
	    System.out.println(value);
	    field.setAccessible(false);


3. 获取某个类的静态方法执行

对于private方法:

	    Method method = taskClass.getDeclaredMethod("print2");
	    method.setAccessible(true);
	    method.invoke(taskClass, null);
	    method.setAccessible(false);


对于public方法:

	    Method method = taskClass.getMethod("print4");
	    method.invoke(taskClass, null);


对于带参数的方法调用

	    Class[] argclass = {int.class,String.class};
	    Object [] arg={1,"1"};
	    Method method3 = taskClass.getMethod("print5",argclass);
	    method2.invoke(taskClass, arg);

   
4. 获取某个对象的属性

	public Object getAndChangeObjectProperty(Object obj,String fieldName)
	{
		Class<?> taskClass = obj.getClass();
		Object value = null;
		try
        {
	        Field field =taskClass.getDeclaredField(fieldName);
	        field.setAccessible(true);
	        field.set(obj, "new");
	        value = field.get(obj);
	        field.setAccessible(false);
        } catch (NoSuchFieldException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (SecurityException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalArgumentException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalAccessException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
		return value;
	}


5. 获取某个对象的方法执行

	public void getAndInvokeMethod(Object obj,Object [] args,String methodName)
	{
		Class<?> taskClass = obj.getClass();
		Method method= null;
		try
        {
			if(args==null)
			{
				method = taskClass.getDeclaredMethod(methodName);				
			}
			else
			{
			    Class[] argclass = {int.class,String.class};
			    method = taskClass.getDeclaredMethod(methodName, argclass);
			}
	        method.setAccessible(true);
	        method.invoke(obj, args);
	        method.setAccessible(false);
        } catch (NoSuchMethodException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (SecurityException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalAccessException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalArgumentException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (InvocationTargetException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
	}


test.getAndInvokeMethod(this, null, "print1")和test.getAndInvokeMethod(this, args, "print5")有参和无参时调用方法。
    Java的反射最大的特别是在运行时来做上面的操作。上面的都是一些基本用法,反射提供很多其他好用的方法,如判断某一个对象是否是类的对象的isinstance;一些获取基类的属性和方法(通过继承类的class.getSuperclass()后得到基类的class,后面的操作类似)等。
    个人对于object.getclass与Class.Forname(package.classname)区别的理解:
前者是得到内存中的类对象,而后者得到的是内存中的类文件,但是最终得到的都是内存中同一块一样的东西,因为对于个类文件来讲只会在java虚拟机中加载一个类对象。前面的例子中,对于不是静态属性或者方法的是否可调用决定在于具体的对象是否在堆中建立。