`

java通过反射操作类

 
阅读更多

一、使用原生反射方式

1. 新建一个普通的java类-Student

public class Student{
	private String userName;
	private String passWord;
	
	public Student(){}
	
	public Student(String userName,String passWord){
		this.userName = userName;
		this.passWord = passWord;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassWord() {
		return passWord;
	}
	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}
	@Override
	public String toString() {
		return "Student [userName=" + userName + ", passWord=" + passWord + "]";
	}

2. 通过反射方法-getDeclaredMethods()获取该类中的全部方法

注:通过getDeclaredMethods获取该类中所有方法,包括公共、保护、默认(包)访问和私有方法,当然不包括其继承的方法(比如Student的隐形继承的类Object中的方法);通过getMethods获取所有公用(public)方法包括其继承类的公用方法(即包含父类Object中的方法)

 

Class<?> clazz = null;
try {
	clazz = Class.forName("com.maps.test.proxy.Student");
} catch (ClassNotFoundException e) {
	e.printStackTrace();
}
Method[] methods = clazz.getDeclaredMethods();
for(int i=0;i<methods.length;i++){
	Method method = methods[i];
	
	Parameter[] parameters = method.getParameters();
	StringBuilder sbf = new StringBuilder("(");
	for(int m=0;m<parameters.length;m++){
		Parameter parameter = parameters[m];
		String parameterName = parameter.getName();
		int modify = parameter.getModifiers();
		String parameterModify = Modifier.toString(modify);
		String parameterType = 
                parameter.getType().getSimpleName();
		sbf.append(parameterModify).append(" 
                ").append(parameterType).append(" 
                ").append(parameterName).append(",");
	}
	if(sbf.lastIndexOf(",")>=0){
		sbf.deleteCharAt(sbf.length()-1);	
	}
	sbf.append(")");
	System.out.println("[methodInfo:{methodName:"+method.getName()+",returnType:"
        +method.getReturnType().getName()+"}"+",parameterInfo:{"+sbf.toString()+"}]");
}

 以上代码运行结果-输出了每一个方法和方法中的参数的访问权限、类型、名称信息

 

[methodInfo:{methodName:toString,returnType:java.lang.String,methodModify:public},parameterInfo:{()}]
[methodInfo:{methodName:setUserName,returnType:void,methodModify:public},parameterInfo:{( String arg0)}]
[methodInfo:{methodName:setPassWord,returnType:void,methodModify:public},parameterInfo:{( String arg0)}]
[methodInfo:{methodName:getPassWord,returnType:java.lang.String,methodModify:public},parameterInfo:{()}]
[methodInfo:{methodName:getUserName,returnType:java.lang.String,methodModify:public},parameterInfo:{()}]

 

3. 通过反射方法-getDeclaredFields()获取该类中的所有属性

注:getDeclaredFields方法用于获得类中的所有的属性,包括public、private和proteced、default,但是不包括父类中的属性;getFields方法获得类中的所有的公共(public)的字段,包括父类中声明的属性

 

Field[] fields = clazz.getDeclaredFields();
for(int i=0;i<fields.length;i++){
	Field field = fields[i];
	String fieldName = field.getName();//获取属性的名称
	Class<?> fieldType = field.getType();//获取属性的类型
	String fieldTypeValue = fieldType.getSimpleName(); //获取属性的简单
        类型,即不带java.lang前缀
	int modify = field.getModifiers();//获取数学的访问权限
	String modifyVal = Modifier.toString(modify);
	System.out.println("[fieldInfo:{fieldModify:"+modifyVal+",fieldType
        :"+fieldTypeValue+",fieldName:"+fieldName+"}]");
}

 

以上代码运行结果-输出了Student类中定义的两个属性

[fieldInfo:{fieldModify:private,fieldType:String,fieldName:userName}]
[fieldInfo:{fieldModify:private,fieldType:String,fieldName:passWord}]

 

 4. 通过反射调用类中的方法

 

/**
 * 通过类路径加载类Student
 */
Class<?> clazz = null;
try {
	clazz = Class.forName("com.maps.test.proxy.Student");
} catch (ClassNotFoundException e) {
	e.printStackTrace();
}
try {
	//实例化Studnt对象
	Object obj = clazz.newInstance();
	//获取Student中的方法名为setUserName,参数数量只有一个,参数类型
        为String的方法体
	Method setUserNameMethod = 
        clazz.getMethod("setUserName",String.class);
	//通过反射invoke调用Student对象中的setUseName方法,并且传递参
        数“maps”
	setUserNameMethod.invoke(obj,"maps");
	
	/**
	 * 直接修改Student中的属性值
	 */
	Field field = clazz.getDeclaredField("userName");//获取Studnt中名
        称为userName的属性
        field.setAccessible(true);//设置该属性的可访问权限
        field.set(obj, "mapingsheng");//然后把该属性的值设置
        为“mapingsheng”
	
	/**
	 * 通过反射调用getUserName方法获取上一步设置好的属性-userName的
        值
	 */
	Method getUserNameMethod = clazz.getMethod("getUserName");
	String userNameValue = (String) 
        getUserNameMethod.invoke(obj);
	System.out.println(userNameValue);
} catch (Exception e) {
	e.printStackTrace();
}
 以上代码运行结果:

 

mapingsheng

二、使用java动态代理-InvocationHandler方式

代理就是通过中间的代理对象间接的调用真实对象的方法的应用模式,在java中,java.lang.reflect API提供了API提供了proxy类和InvocationHandler接口来实现动态代理操作。Proxy类根据给定的参数创建动态代理类。 InvocationHandler调用动态代理类的方法。 以下将详细讨论所有这些情况:

  • java.lang.reflect.Proxy是一个提供静态方法来创建动态代理类的类。Proxy类中有一个newProxyInstance()方法定义如下:
public static Object newProxyInstance (ClassLoader loader ,Class <?> [] 
interfaces ,InvocationHandler h)
 这个方法中的三个参数的意义:

 

ClassLoader:这个类加载器将定义动态代理类。类加载器可以通过正在创建其动态代理的类或接口来获取。

interfaces:第二个参数是被代理的类所实现的所有接口的数组

InvocationHandler:第三个参数是传递实现java.lang.reflect.InvocationHandler的类的实例

  • java中的InvocationHandler是java.lang.reflect包中的接口。InvocationHandler由用户类实现,以调用动态代理类的方法。invoke方法的语法如下
  • Object invoke(Object proxy ,Method m ,Object [] args)
  • 这个方法中的三个参数的意义:

    Object:这是调用方法的代理实例。

    Method:这对应于在代理实例上调用的接口方法。

    Object []:它包含一个在方法调用中传递的参数数组。

    - 具体使用代码演示java的动态代理操作

    通过一个结婚的场景来模拟动态代理场景,比如日常生活中要结婚的话,需要预定场地和吃饭的酒店,并且出行需要预定汽车服务。

    • 一个代理结构(中介)提供了很多套餐(酒店+出行套餐、酒店+婚礼主持+出行套餐等等)–代理类MarryProxy
    • 这个代理机构提供了很多套餐服务,一般开发中都是面向接口编程(MarryPackageService、MarryPackageServiceImpl)
    • 我们采取最经济的套餐(酒店+出行套餐)来讲,可以看到上面场景一共需要提供如下类:
      1. 定义一个结婚套餐服务接口
        /**
         * 结婚套餐(提供酒店+出行服务)
         * @author mapingsheng
         */
        public interface MarryPackageService {
        	
        	/**
        	 * 提供酒店服务,一站式解决婚礼举办、就餐问题
        	 * @return
        	 */
        	public String hotel(String address,String hotelName);
        	/**
        	 * 提供用车服务,解决出行问题
        	 * @return
        	 */
        	public String car(String carName);
        }
         
      2. 定义一个结婚套餐接口的实现类
        /**
         * 结婚套餐(提供酒店+出行服务)具体业务类
         * @author mapingsheng
         */
        public class MarryPackageServiceImpl implements
      3.  MarryPackageService{
        	@Override
        	public String hotel(String address, String hotelName) {
        		Date date = new Date();
        		SimpleDateFormat sf = new SimpleDateFormat
      4.                ("yyyy-MM-dd HH:mm:ss");
        		
        		return sf.format(date)+" 【"+address+" "+hotelName+"
      5.               】 提
                        供就餐服务";
        	}
        	@Override
        	public String car(String carName) {
        		return "【"+carName+"】  提供出行服务";
        	}
        }
         
      6. 定义一个代理结构-代理类

    注:代理类必须实现InvocationHandler接口,我们在构造方法中初始化被代理的对象

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class MarryProxy implements InvocationHandler{
    	private Object obj;//这个就是我们要代理的真实对象
    	
    	/**
    	 * 通过构造函数初始化代理对象
    	 * @param obj
    	 */
    	public  MarryProxy(Object obj){
    		 this.obj = obj;
    	 }
    	/**
    	 * 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联
  • 的handler对象的invoke方法来进行调用
    	 */
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)
  •         throws Throwable {
    		return method.invoke(obj, args);
    	}
    }
  • import java.lang.reflect.InvocationHandler;
    1. 新建一个测试类
      import java.lang.reflect.Proxy;
      public class MarryClient {
      	public static void main(String[] args) {
      	//我们要代理的真实对象
    2. MarryPackageService marryPackageService =
    3.  new MarryPackageServiceImpl();
      		//初始化代理类
         InvocationHandler handler = new MarryProxy(marryPackageService);
         //通过Proxy的newProxyInstance方法来创建我们的代理对象
         Object obj = Proxy.newProxyInstance(marryPackageService.getClass
    4.    ().getClassLoader(), 											marryPackageService.getClass().getInterfaces(), 									handler);
       MarryPackageService marryService = (MarryPackageService) obj;
       String hotelInfo = marryService.hotel("北京市海淀区中关村南大街8号",
    5.  "香格里拉大酒店");
      String carInfo = marryService.car("奥迪A6");
      System.out.println(hotelInfo+" "+carInfo);
      	}
      }
       以上代码运行结果:

      2017-05-10 14:41:57 【北京市海淀区中关村南大街8号 香格里拉大酒店】 提供就餐服务 【奥迪A6】 提供出行服务

分享到:
评论

相关推荐

    java 通过反射获取枚举类,及枚举类的值,枚举类枚举实例名

    在Java编程语言中,反射(Reflection)是一种强大的工具,它允许程序在运行时检查和操作类、接口、字段和方法等对象。枚举(Enumeration)是Java中的一个特殊类类型,用于定义一组常量。本项目"test-enum-demo-...

    java 通过反射获取类上注解,方法上注解,注解里的值及方法参数

    在Java编程中,注解...这个示例涵盖了Java中使用反射获取注解的基本操作,包括类、方法、注解的值和方法参数。通过实践这个例子,你可以更好地理解和掌握这些概念,从而在实际项目中更有效地利用注解和反射。

    java 利用反射获取内部类静态成员变量的值操作.docx

    接下来,我们将通过一个具体的例子来演示如何使用Java反射获取内部类的静态成员变量的值。 ##### 示例代码分析 假设我们有如下的类结构: ```java public class Goods { static class Apple { // 内部类 public ...

    Java反射调用工具类

    这个“Java反射调用工具类”可能是为了简化和封装这些复杂的反射操作而创建的一个实用工具类。 首先,`JobProxy.java`可能是一个代理类,它利用反射来动态地调用目标对象的方法。在Java中,代理模式通常用于在不...

    java反射机制工具类

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息。这个特性使得Java具备了高度的灵活性,能够在运行时动态地发现和使用类的属性和方法,即使这些信息在编译时...

    java的类反射

    Java的类反射是Java语言中一个强大的特性,它允许程序在运行时检查并操作类、接口、字段和方法的信息。这种动态类型的能力使得Java代码能够更加灵活,可以处理未知类型的对象,实现元编程,以及在运行时创建和访问类...

    java反射 java反射 java反射java反射

    Java反射是Java编程语言中的一个重要特性,它允许程序在运行时动态地获取类的信息并操作类的对象。在Java中,反射机制提供了强大的能力,包括在运行时检查类的结构、创建对象实例、调用方法以及访问和修改字段值。...

    Java反射动态加载实例类

    通过本示例,我们不仅理解了Java反射的基本概念和用途,还学会了如何利用反射动态加载并操作实例类。反射提供了一种灵活的方式来处理类和对象,尤其是在编写框架和插件系统时,能够根据运行时的条件动态地加载和执行...

    Java 通过反射给实体类赋值操作

    Java 通过反射给实体类赋值操作 Java 通过反射给实体类赋值操作是 Java programming 语言中的一种常用技术,通过使用 Java 的反射机制,可以将请求中的参数赋值给实体类对象,从而简化了数据的处理过程。下面是该...

    JAVA反射机制的入门代码

    总的来说,"JAVA反射机制的入门代码"是初学者理解Java反射机制的好教材,通过它,你可以学习如何动态地操作Java类,提高代码的灵活性,并掌握处理`properties`文件的基础方法。在深入学习和实践中,你将进一步理解...

    java反射例子,封装了一个反射帮助类

    Java反射是Java编程语言中的一个重要特性,它允许运行时访问和操作类、接口、字段和方法等信息。在Java中,反射提供了动态类型的能力,使我们可以在程序运行时检查类的信息,创建和调用对象的方法,甚至修改对象的...

    java反射操作父类所有属性和方法

    ### Java反射操作父类所有属性和方法 #### 一、引言 在Java编程语言中,反射(Reflection)是一项强大的特性,它允许程序在运行时动态地获取类的信息,并能够直接操作这些信息。通过反射,我们可以获取类的字段、...

    java反射,获取所有属性、方法以及List集合类

    如果方法返回一个List集合,可以通过反射操作这个List。 ```java Object obj = clazz.newInstance(); // 创建对象,如果类有无参构造器 Method getListMethod = clazz.getMethod("getListMethod"); // 假设有个...

    Java方法反射调用demo

    总的来说,Java反射提供了强大的能力,让我们可以在运行时动态地操作类和对象。尽管它增加了程序的复杂性,但在某些特定情况下,如插件系统、序列化、测试和调试等方面,反射都是不可或缺的工具。然而,应当谨慎使用...

    java 反射中操作数组

    总结来说,Java反射提供了对数组的动态操作能力,包括创建数组、设置和获取数组元素、以及处理类中声明的数组字段。这种能力使得代码更加灵活,但也增加了潜在的错误风险,因此在使用时应谨慎并充分测试。

    java 反射得到某个方法

    总结一下,Java反射机制为我们提供了在运行时检查和操作类、方法的能力。通过`Class.forName()`获取Class对象,再利用`getMethod()`获取方法,最后使用`invoke()`执行方法。在实际开发中,理解并谨慎使用反射,能够...

    Java反射操作(需要commons-beanutils-1.8.2.jar)

    在标题中提到的“Java反射操作”通常是指在运行时动态地获取类的信息(如类名、方法、字段)并调用它们的能力。这在很多场景下非常有用,比如在框架开发、插件系统、序列化、元数据处理等。 Apache Commons ...

    java中反射的概念

    总的来说,Java反射机制是面向对象编程的一个重要补充,它扩展了Java程序的动态性,允许程序员在运行时访问和操作类的内部结构,增强了代码的灵活性。理解和熟练掌握反射技术,对于提升Java编程能力,尤其是处理复杂...

    java之反射优化(缓存思路)源码

    在Java编程中,反射(Reflection)是一个强大的工具,它允许我们在运行时检查和操作类、接口、字段和方法。然而,反射操作通常比直接的Java代码执行慢,因为它涉及到动态类型检查和方法调用。因此,为了提高性能,...

    java bean 反射,

    java通过反射,修改操作类......

Global site tag (gtag.js) - Google Analytics