`
xyheqhd888
  • 浏览: 403687 次
  • 性别: Icon_minigender_1
  • 来自: 秦皇岛
社区版块
存档分类
最新评论

使用反射生成与操作对象(二)

阅读更多

1. 修改成员值:

    尽管直接存取类的域成员是不被鼓励的,但仍可以直接存取公开的域成员,甚至也可以通过反射机制来存取私有域成员。下面以一个实例来说明,首先编写一个TestField类。

   

package ysu.hxy;

public class TestField
{
   public int testInt;
   public String testString;

   public String toString()
	{
	   return testInt + ":" +testString;
	}
}

 下面的范例利用反射机制动态加载类来存取域成员:

package ysu.hxy;

import java.lang.reflect.Field;

public class AssignFieldDemo 
{
	public static void main(String[] args) 
	{
		try
		{
			Class c = Class.forName(args[0]);
			Object targetObj = c.newInstance();
            
			//返回域成员
			Field testInt = c.getField("testInt");
			testInt.setInt(targetObj,99);

			Field testString = c.getField("testString");
			testString.set(targetObj,"caterpillar");

			System.out.println(targetObj);
		}
		catch(ArrayIndexOutOfBoundsException e)
		{
			System.out.println("没有指定类");
		}
		catch(ClassNotFoundException e)
		{
			System.out.println("找不到指定的类");
		}
		catch(SecurityException e)
		{
			e.printStackTrace();
		}
		catch(NoSuchFieldException e)
		{
			System.out.println("找不到指定的域成员");
		}
		catch(InstantiationException e)
		{
			e.printStackTrace();
		}
		catch(IllegalAccessException e)
		{
			e.printStackTrace();
		}
	}
}

运行结果:

D:\hxy>java ysu.hxy.AssignFieldDemo ysu.hxy.TestField
99:caterpillar

如果有必要,也可以通过反射机制存取私有的域成员,如:

Field privateField = c.getDeclaredField("privateField");
privateField.setAccessible(true);
privateField.setInt(targetObj,99);

2.再看数组对象:

  在Java中数组也是一个对象,也会有一个Class实例来表示它。如下:

package ysu.hxy;

public class ArrayDemo {
    public static void main(String[] args) {
        short[] sArr = new short[5];
        int[] iArr = new int[5];
        long[] lArr = new long[5];
        float[] fArr = new float[5];
        double[] dArr = new double[5];
        byte[] bArr = new byte[5];
        boolean[] zArr = new boolean[5];
        String[] strArr = new String[5];

        System.out.println("short 数组类:" + sArr.getClass());
        System.out.println("int 数组类:" + iArr.getClass());
        System.out.println("long 数组类:" + lArr.getClass());
        System.out.println("float 数组类:" + fArr.getClass());
        System.out.println("double 数组类:" + dArr.getClass());
        System.out.println("byte 数组类:" + bArr.getClass());
        System.out.println("boolean 数组类:" + zArr.getClass());
        System.out.println("String 数组类:" + strArr.getClass());
    }
}

  运行结果:

D:\hxy>java ysu.hxy.ArrayDemo
short 数组类:class [S
int 数组类:class [I
long 数组类:class [J
float 数组类:class [F
double 数组类:class [D
byte 数组类:class [B
boolean 数组类:class [Z
String 数组类:class [Ljava.lang.String;

若要使用反射机制动态生成数组,可以使用java.lang.reflect.Array来协助。下面的这个范例示范了如何生成String数组:

package ysu.hxy;

import java.lang.reflect.Array;

public class NewArrayDemo
{
	public static void main(String[] args) 
	{
		Class c = String.class;
		Object objArr = Array.newInstance(c,5);

		for(int i = 0;i < 5;i++)
		{
			Array.set(objArr,i,i+"");
		}

		for(int i = 0;i < 5;i++)
		{
			System.out.print(Array.get(objArr,i) + " ");
		}
		System.out.println();

		String[] strs = (String[]) objArr;
		for(String s : strs)
		{
			System.out.print(s+ " ");
		}
	}
}

 Array.newInstance()的第一个参数指定元素类型,而第二个参数指定数组长度。此方法还有另一个版本,用于创建二维数组,如下:

package onlyfun.caterpillar;
 
import java.lang.reflect.Array;
 
public class NewArrayDemo2 {
    public static void main(String[] args) {
        Class c = String.class;
        
        // 打算建立一个3*4数组
        int[] dim = new int[]{3, 4};
        Object objArr = Array.newInstance(c, dim);
        
        for(int i = 0; i < 3; i++) {
            Object row = Array.get(objArr, i);
            for(int j = 0; j < 4; j++) {
                Array.set(row, j, "" + (i+1)*(j+1));
            }
        }
        
        for(int i = 0; i < 3; i++) {
            Object row = Array.get(objArr, i);
            for(int j = 0; j < 4; j++) {
                System.out.print(Array.get(row, j) + " ");
            }
            System.out.println();
        }
    }
}

 如果要得知数组元素的类型,可以在取得数组的Class实例之后,使用Class实例的getComponentType()方法,所取回的是元素的Class实例。例如:

int[] iArr = new int[5];
System.out.println(iArr.getClass().getComponentType());

3. Proxy类:

    java.lang.reflect.Proxy类,可协助实现动态代理功能。例如:假设打算开发一个HelloSpeaker类,其中有一个hello()方法,想要在这个hello()调用前后加上记录的功能,但又不想将记录的功能写到HelloSpeaker类中。这时可以使用Proxy类来实现动态代理。

    要实现动态代理,首先要定义所要代理的接口。如下定义了有hello()方法的IHello接口。

package ysu.hxy;

public interface IHello
{
	public void hello(String name);
}

 HelloSpeaker类实现了IHello接口,如下:

package ysu.hxy;

public class HelloSpeaker implements IHello 
{
	public void hello(String name)
	{
		System.out.println("Hello," + name);
	}
}

 可以实现一个处理记录的处理器(Handler),让处理器在调用hello()方法的前后进行记录的动作。一个处理器必须实现java.lang.reflect.InvocationHandler接口,InvocationHandler有一个invoke()方法必须实现

package ysu.hxy;
import java.util.logging.*;
import java.lang.reflect.*;

public class LogHandler implements InvocationHandler 
{
	private Logger logger = 
		Logger.getLogger(this.getClass().getName());
    
	private Object delegate;

	//绑定要代理的对象
	public Object bind(Object delegate)
	{
		this.delegate = delegate;
		//建立并返回代理对象 
		return Proxy.newProxyInstance(
			delegate.getClass().getClassLoader(),
			//要被代理的接口
			delegate.getClass().getInterfaces(),
				this);
	}

	//代理要调用的方法,并在其前后增加行为
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
	{
			 Object result = null;
			 try
			  {
				 logger.log(Level.INFO,"method starts..." + method.getName());
				 result = method.invoke(delegate,args);
				 logger.log(Level.INFO,"method endss..." + method.getName());
			  }
			  catch(Exception e)
			  {
				 logger.log(Level.INFO,e.toString());
			  }
		return result;		
	}
}

 主要的概念是使用Proxy.newProxyInstance()方法建立一个代理对象,建立代理对象时必须告知所要代理的操作接口,然后可以操作所建立的代理对象,在每次操作时会调用InvocationHandler的invoke()方法,invoke()方法会传入被代理对象的方法名称与运行变量,实际上要运行的方法交由method.invoke()。在method.invoke()前后加上记录动作,method.invoke()返回的对象是实际方法运行后的回传结果。先来看看一个运行的例子:

package ysu.hxy;

public class ProxyDemo
{
	public static void main(String[] args) 
	{
		LogHandler handler = new LogHandler();
		IHello speaker = new HelloSpeaker();

		//代理speaker的对象
		IHello speakerProxy = 
			(IHello)handler.bind(speaker);

		speakerProxy.hello("Justin");
	}
}

 运行结果:

D:\hxy>java ysu.hxy.ProxyDemo
2009-4-6 19:06:24 ysu.hxy.LogHandler invoke
信息: method starts...hello
Hello,Justin
2009-4-6 19:06:24 ysu.hxy.LogHandler invoke
信息: method endss...hello

通过代理机制,在不将记录动作写入HelloSpeaker类程序代码的情况下,可以为其加入记录的功能。这只是在hello()方法前后由代理对象speakerProxy先执行记录功能而已,真正运行hello()方法时才使用speaker对象。

分享到:
评论

相关推荐

    Java反射 JavaBean对象自动生成插入,更新,删除,查询sql语句操作.docx

    Java反射 JavaBean对象自动生成插入,更新,删除,查询sql语句操作.docx

    仿hibernate动态生成sql保存对象

    反射对象生成sql,保存对象。 里面还差,存储过程、批量操作、动态sql 还差一个配套的工具(根据数据库字段生成对象)

    Java反射 JavaBean对象自动生成插入,更新,删除,查询sql语句操作

    主要介绍了Java反射 JavaBean对象自动生成插入,更新,删除,查询sql语句操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    使用反射技术和Facade模式演示封装数据库操作--ORM原理

    于是,使用Facade模式和反射技术模拟Hibernate框架技术演示怎样书封装数据库的操作。 环境:Windows XP Professional, JDK 1.6, Eclipse 3.3 Europa, SQL Server 2000 使用步骤: 1. 下载解压之后,使用Eclipse导入...

    xml与反射.txt

    反射是一种间接操作目标对象的机制,在程序程序运行时获取或者设置对象自身的信息。 只要给定类的名字,就可以通过反 射获取类的所有信息,接着便能调用它的任何一个方法和属性。 反射的步骤有哪些? 第一:获取类...

    ORM框架-VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG 4.2】 2011迎新版

    是一款专门为VB/C#.Net数据库程序员开发量身定做的(ORM框架)代码生成工具,所生成的代码基于面向对象、分层架构设计、ORM并参考微软Petshop中的经典思想,使用改进的抽象工厂设计模式及反射机制等。目前直接支持...

    C#.Net实体代码生成工具 v3.0

    C#.Net 数据库程序员开发量身定做的自动代码生成工具,所生成的代码基于面向对象的思想和分层架构设计,并参考了微软Petshop中经典的思想和设计模式,融入了工厂模式,反射机制,ORM等思想。从数据库中提取表对应的...

    C#.Net实体代码生成工具 v3.1

    是一款专门为 C#.Net 数据库程序员开发量身定做的自动代码生成工具,所生成的代码基于面向对象的思想、分层架构设计及ORM,并参考了微软Petshop中经典的思想,融入了工厂模式等设计模式,反射机制等。从数据库中提取...

    java反射.ppt

    每当一個类被载入时,JVM就自动为其生成一个Class对象,通过操作class对象,我们可以得到该对象的所有成员并操作它们 public class ClassDemo { public static void main(String[] args) { String name = “ACCP"; ...

    超强的C#代码生成工具,支持ACCESS,ORACLE,SQL 最新

    4、可选择不生成缓存代码、“缓存对象”、“聚合缓存依赖”及“缓存对象+聚合缓存依赖” 5、可选择要生成的层 6、可生成用户控件及后台代码 7、无需输入命令,即可为数据库,表启用缓存依赖 8、自动生成SqlServer和...

    C#.Net实体代码生成工具 v3.0 (20090830最新版)

    是一款专门为 C#.Net 数据库程序员开发量身定做的自动代码生成工具,所生成的代码基于面向对象的思想、分层架构设计及ORM,并参考了微软Petshop中经典的思想,融入了工厂模式等设计模式,反射机制等。从数据库中提取...

    ORM框架-VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG 4.3】

    VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG】是一款专门为VB/C#.Net数据库程序员开发量身定做的(ORM框架)代码生成工具,所生成的代码基于面向对象、分层架构、ORM,使用改进的抽象工厂设计模式及反射机制...

    Java高级程序设计实战教程第三章-Java反射机制.pptx

    对于任意一个对象,都能够调用它的任意一个方法,常见的应用如下 逆向代码 ,例如反编译 与注解相结合的框架 例如Retrofit 单纯的反射机制应用框架 例如EventBus 2.x 动态生成类框架 例如Gson Java高级程序设计实战...

    Codematic .Net代码自动生成器 Beta版(.Net 2.0版)

    Codematic (2.0版)是一款为 C# 数据库程序员设计的自动代码生成器,Codematic 生成的代码基于基于面向对象的思想和三层架构设计,结合了Petshop中经典的思想和设计模式,融入了工厂模式,反射机制等等一些思想。...

    java 反射Reflection;Class类

    是被视为动态语言的关键,反射机制允许程序在执行期借助Reflection API取得任何类的内部信息并能直接操作任意对象的内部属性及方法。 java反射机制所提供的功能: 生成动态代理 在运行时判断任意一个对象所属的类 在...

    LTP.Net代码自动生成器(DbToCode)

    DbToCode 是一款为 C# 数据库程序员设计的自动代码生成器,DbToCode 生成的代码基于基于面向对象的思想和三层架构设计,结合了Petshop中经典的思想和设计模式,融入了工厂模式,反射机制等等一些思想。采用 Model +...

    傲.NET代码生成器 1.2.4

    生成的代码基于面向对象的思想和三层架构设计,结合了目前最经典的设计思想和设计模式,融入了工厂模式,反射机制等等一系列操作。能实现对ACCESS,mysql,SQLSERVER2000,ORACLE等多种数据库进行操作,提供了 SQL查询...

    java中的反射

    使用Java的反射机制,可以在运行时期动态加载类并生成对象,操作对象上的方法,改变类成员的值,甚至连私有成员的值也可以改变。

    傲世源.NET代码生成器V1.0

    傲世源代码生成器是一款为C#数据库程序员设计的自动代码生成器,傲世源 生成的代码基于面向对象的思想和三层架构设计,结合了目前最经典的设计思想和设计模式,融入了工厂模式,反射机制等等一系列操作。能实现对...

    ORM框架-VB/C#.Net实体代码生成工具(EntitysCodeGenerate)ECG4.3.pdf

    摘要:VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG】是一款专门为.Net数据库程序开发量身定做的(ORM框架)代码生成工具,所生成的程序代码基于面向对象、分层架构、ORM及反射+工厂设计模式等。支持.Net1.1...

Global site tag (gtag.js) - Google Analytics