java反射机制与动态代理2

本文详细介绍了如何使用Java反射机制创建对象实例,包括无参构造器和有参构造器的情况,并展示了如何通过反射调用方法及修改字段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欲生成对象实体,在Reflection 动态机制中有两种作法,一个针对“无自变量ctor”,一个针对“带参数ctor”。如果欲调用的是“带参数ctor“就比较麻烦些,不再调用Class的newInstance(),而是调用Constructor 的newInstance()。首先准备一个Class[]做为ctor的参数类型,然后以此为自变量调用getConstructor(),获得一个专属ctor。接下来再准备一个Object[] 做为ctor实参值,调用上述专属ctor的newInstance()。

 

下面做个例子,该例子的反射对象没有构造方法(实际上是默认的构造方法),无自变量,动态生成“Class object 所对应之class”的对象实体,代码如下:

 

首先建立com.lansin.ghk包,在其下建立两个类:Person.java和Test1.java。

 

Java代码 复制代码
  1. package com.lansin.ghk;   
  2.   
  3. public class Person{   
  4.        
  5.     private String name;   
  6.        
  7.     private String address;   
  8.   
  9.     public String getName() {   
  10.         return name;   
  11.     }   
  12.   
  13.     public void setName(String name) {   
  14.         this.name = name;   
  15.     }   
  16.   
  17.     public String getAddress() {   
  18.         return address;   
  19.     }   
  20.   
  21.     public void setAddress(String address) {   
  22.         this.address = address;   
  23.     }   
  24.   
  25.     @Override  
  26.     public String toString() {   
  27.         return "名称为" + this.getName() + ", 地址为" + this.getAddress();   
  28.     }   
  29. }  
package com.lansin.ghk;

public class Person{
	
	private String name;
	
	private String address;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "名称为" + this.getName() + ", 地址为" + this.getAddress();
	}
}

 Person.java

 

Java代码 复制代码
  1. package com.lansin.ghk;   
  2.   
  3. import java.lang.reflect.Field;   
  4. import java.lang.reflect.Method;   
  5.   
  6. public class Test1 {   
  7.   
  8.     public static void main(String[] args) throws Exception {   
  9.            
  10.         Class<?> classType = Class.forName("com.lansin.ghk.Person");   
  11.            
  12.         Object obj = null;   
  13.            
  14.         obj = classType.newInstance();   
  15.            
  16.         Field fields[] = classType.getDeclaredFields();   
  17.            
  18.         for(int i=0; i<fields.length;i++){   
  19.             Field field = fields[i];   
  20.                
  21.             String fieldName = field.getName();   
  22.                
  23.             String firstLetter = fieldName.substring(01).toUpperCase();   
  24.                
  25.             String getMethodName = "get" + firstLetter + fieldName.substring(1);   
  26.                
  27.             String setMethodName = "set" + firstLetter + fieldName.substring(1);   
  28.                
  29.             Method getMethod = classType.getMethod(getMethodName);   
  30.                
  31.             Method setMethod = classType.getMethod(setMethodName,field.getType());   
  32.                
  33.             if("name".equals(fieldName)){   
  34.                 setMethod.invoke(obj, "迈克·泰森");   
  35.             }   
  36.             else if("address".equals(fieldName)){   
  37.                 setMethod.invoke(obj, "美国");   
  38.             }              
  39.         }   
  40.            
  41.         System.out.println(obj);   
  42.     }   
  43. }  
package com.lansin.ghk;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test1 {

	public static void main(String[] args) throws Exception {
		
		Class<?> classType = Class.forName("com.lansin.ghk.Person");
		
		Object obj = null;
		
		obj = classType.newInstance();
		
		Field fields[] = classType.getDeclaredFields();
		
		for(int i=0; i<fields.length;i++){
			Field field = fields[i];
			
			String fieldName = field.getName();
			
			String firstLetter = fieldName.substring(0, 1).toUpperCase();
			
			String getMethodName = "get" + firstLetter + fieldName.substring(1);
			
			String setMethodName = "set" + firstLetter + fieldName.substring(1);
			
			Method getMethod = classType.getMethod(getMethodName);
			
			Method setMethod = classType.getMethod(setMethodName,field.getType());
			
			if("name".equals(fieldName)){
				setMethod.invoke(obj, "迈克·泰森");
			}
			else if("address".equals(fieldName)){
				setMethod.invoke(obj, "美国");
			}			
		}
		
		System.out.println(obj);
	}
}

 Test1.java

 

运行结果为:“名称为迈克·泰森, 地址为美国”。

 

下面做个例子,该例子的反射对象包含构造方法,有自变量,动态生成“Class object 所对应之class”的对象实体,代码如下:

 

有构造方法的Person类只需在上面的Person类里加一个构造方法;Test2类“反射”Person。

 

Java代码 复制代码
  1. package com.lansin.ghk;   
  2.   
  3. public class Person{   
  4.        
  5.     private String name;   
  6.        
  7.     private String address;   
  8.        
  9.     public Person(String name, String address){   
  10.         this.name = name;   
  11.         this.address = address;   
  12.     }   
  13.   
  14.     public String getName() {   
  15.         return name;   
  16.     }   
  17.   
  18.     public void setName(String name) {   
  19.         this.name = name;   
  20.     }   
  21.   
  22.     public String getAddress() {   
  23.         return address;   
  24.     }   
  25.   
  26.     public void setAddress(String address) {   
  27.         this.address = address;   
  28.     }   
  29.   
  30.     @Override  
  31.     public String toString() {   
  32.         return "名称为" + this.getName() + ", 地址为" + this.getAddress();   
  33.     }   
  34. }  
package com.lansin.ghk;

public class Person{
	
	private String name;
	
	private String address;
	
	public Person(String name, String address){
		this.name = name;
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "名称为" + this.getName() + ", 地址为" + this.getAddress();
	}
}

 修改后的Person.java

 

Java代码 复制代码
  1. package com.lansin.ghk;   
  2.   
  3. import java.lang.reflect.Constructor;   
  4.   
  5. public class Test2 {   
  6.   
  7.     public static void main(String[] args) throws Exception {   
  8.            
  9.         Class<?> c = Class.forName("com.lansin.ghk.Person");   
  10.            
  11.         Class[] pTypes = new Class[]{String.class, String.class};   
  12.            
  13.         Constructor ctor = c.getConstructor(pTypes);   
  14.            
  15.         Object obj = null;   
  16.            
  17.         Object[] arg = new Object[]{"迈克·泰森""美国"};   
  18.            
  19.         obj = ctor.newInstance(arg);   
  20.            
  21.         System.out.println(obj);   
  22.     }   
  23. }  
package com.lansin.ghk;

import java.lang.reflect.Constructor;

public class Test2 {

	public static void main(String[] args) throws Exception {
		
		Class<?> c = Class.forName("com.lansin.ghk.Person");
		
		Class[] pTypes = new Class[]{String.class, String.class};
		
		Constructor ctor = c.getConstructor(pTypes);
		
		Object obj = null;
		
		Object[] arg = new Object[]{"迈克·泰森", "美国"};
		
		obj = ctor.newInstance(arg);
		
		System.out.println(obj);
	}
}

 Test2.java

 

运行,和上个程序结果一样:“名称为迈克·泰森, 地址为美国”。

 

比较上面两段程序:首先要提供一个对象类的地址全称(包名+类名)。

 

(一)对于没有构造函数的类,在运行时刻创建该对象所属类的对象实例:

 

先声明一个泛型Class,

Class<?> classType = Class.forName("com.lansin.ghk.Person");

 

然后由泛型对象classType生成实例,

Object obj = classType.newInstance();

 

接下来调用反射机制提供的各种方法进行动态处理;

 

(二)对于有构造函数的类,在运行时刻创建该对象所属类的对象实例:

 

同样要先声明一个泛型Class,

Class<?> classType = Class.forName("com.lansin.ghk.Person");

 

创建一个“类型类”集合,因为Person类的构造函数有两个string类型的形参,

Class[] pTypes = new Class[]{String.class, String.class};

 

接下来由生成的“由对象在运行时所生成所属类的对象”来创建一个带有形参(是个集合)的构造器,

Constructor ctor = classType .getConstructor(pTypes);

 

最后由构造器生成一个实例对象,但是首先要设定实参,

设定实参:Object[] arg = new Object[]{"迈克·泰森", "美国"};

实例化对象:Object obj = ctor.newInstance(arg);

 

OK了。

 

其实到这里我还有很多细节没有说,这个要在以后的工作中多多学习,多多参考文档,java api是个好东西。

 

下面的例子是在运行时调用Method,代码如下:

 

Java代码 复制代码
  1. public class InvokeTester {   
  2.     public int add(int param1, int param2) {   
  3.         return param1 + param2;   
  4.     }   
  5.   
  6.     public String echo(String msg) {   
  7.         return "echo: " + msg;   
  8.     }   
  9.   
  10.     public static void main(String[] args) throws Exception {   
  11.         Class<?> classType = InvokeTester.class;   
  12.         Object invokeTester = classType.newInstance();   
  13.   
  14.         // 调用InvokeTester对象的add()方法   
  15.         Method addMethod = classType.getMethod("add"new Class[] { int.class,   
  16.                 int.class });   
  17.         Object result = addMethod.invoke(invokeTester, new Object[] {   
  18.                 new Integer(100), new Integer(200) });   
  19.         System.out.println((Integer) result);   
  20.   
  21.         // 调用InvokeTester对象的echo()方法   
  22.         Method echoMethod = classType.getMethod("echo",   
  23.                 new Class[] { String.class });   
  24.         result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });   
  25.         System.out.println((String) result);   
  26.     }   
  27. }  
public class InvokeTester {
	public int add(int param1, int param2) {
		return param1 + param2;
	}

	public String echo(String msg) {
		return "echo: " + msg;
	}

	public static void main(String[] args) throws Exception {
		Class<?> classType = InvokeTester.class;
		Object invokeTester = classType.newInstance();

		// 调用InvokeTester对象的add()方法
		Method addMethod = classType.getMethod("add", new Class[] { int.class,
				int.class });
		Object result = addMethod.invoke(invokeTester, new Object[] {
				new Integer(100), new Integer(200) });
		System.out.println((Integer) result);

		// 调用InvokeTester对象的echo()方法
		Method echoMethod = classType.getMethod("echo",
				new Class[] { String.class });
		result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });
		System.out.println((String) result);
	}
}

 InvokeTester.java

 

这个动作和上述调用“带参数之ctor”相当类似。首先准备一个Class[]做为参数类型(本例指定其中一个是String,另一个是Hashtable),然后以此为自变量调用getMethod(),获得特定的Method object。接下来准备一个Object[]放置自变量,然后调用上述所得之特定Method object的invoke()。
为什么获得Method object时不需指定回返类型?

 

因为method overloading机制要求signature必须唯一,而回返类型并非signature的一个成份。换句话说,只要指定了method名称和参数列,就一定指出了一个独一无二的method。

 

下面的类是运行时变更Field的内容,比较简单,代码如下:

 

Java代码 复制代码
  1. package com.lansin.ghk;   
  2.   
  3. import java.lang.reflect.Field;   
  4.   
  5. public class TestField {   
  6.        
  7.     public double d;   
  8.        
  9.     public static void main(String[] args) throws Exception {   
  10.         Class c = Class.forName("com.lansin.ghk.TestField");   
  11.            
  12.         Field f = c.getField("d");   
  13.            
  14.         TestField obj = new TestField();   
  15.         System.out.println("d= " + (Double)f.get(obj));   
  16.         f.set(obj, 12.34);   
  17.         System.out.println("d= " + obj.d);   
  18.     }   
  19. }  
package com.lansin.ghk;

import java.lang.reflect.Field;

public class TestField {
	
	public double d;
	
	public static void main(String[] args) throws Exception {
		Class c = Class.forName("com.lansin.ghk.TestField");
		
		Field f = c.getField("d");
		
		TestField obj = new TestField();
		System.out.println("d= " + (Double)f.get(obj));
		f.set(obj, 12.34);
		System.out.println("d= " + obj.d);
	}
}

 TestField.java

 

与先前两个动作相比,“变更field内容”轻松多了,因为它不需要参数和自变量。首先调用Class的getField()并指定field名称。获得特定的Field object之后便可直接调用Field的get()和set()。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值