JAVA反射使用手记

Java语言中的反射机制:


    在Java 运行时 环境中,对于任意一个类,能否知道这个类有哪些属性和方法?
    对于任意一个对象,能否调用他的方法?这些答案是肯定的,这种动态获取类的信息,以及动态调用类的方法的功能来源于JAVA的反射。从而使java具有动态语言的特性。


  JAVA反射机制主要提供了以下功能:


      1.在运行时判断任意一个对象所属的类
      2.在运行时构造任意一个类的对象
      3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
      4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)


  Java 反射相关的API简介:


      位于java。lang。reflect包中
        --Class类:代表一个类
        --Filed类:代表类的成员变量
        --Method类:代表类的方法
        --Constructor类:代表类的构造方法
        --Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法


 反射机制的作用:

              1,反编译:.class-->.java

              2,通过反射机制访问java对象的属性,方法,构造方法等;

             这样好像更容易理解一些,下边我们具体看怎么实现这些功能。


具体功能实现:


反射机制获取类有三种方法,我们来获取Employee类型:


//第一种方式:
Class c1 = Class.forName("Employee"); 

//第二种方式:
//java中每个类型都有class 属性.
Class c2 = Employee.class;
 
//第三种方式:
//java语言中任何一个java对象都有getClass 方法 
 Employeee = new Employee();
Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)

创建对象:获取类以后我们来创建它的对象,利用newInstance:


            Class c =Class.forName("Employee");
 
            //创建此Class 对象所表示的类的一个新实例
            Objecto = c.newInstance(); //调用了Employee的无参数构造方法.


实例:


本篇文章为在工作中使用Java反射的经验总结,也可以说是一些小技巧,以后学会新的小技巧,会不断更新。本文不准备讨论JAVA反射的机制,网上有很多,大家随便google一下就可以了。 在开始之前,我先定义一个测试类:


package com.zhushuai.domain;

public class Car {
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public int getMaxSpeed() {
		return maxSpeed;
	}
	public void setMaxSpeed(int maxSpeed) {
		this.maxSpeed = maxSpeed;
	}
	private String brand;
	private String color;
	private int maxSpeed;
	public Car(){
		
	}
	public Car(String brand, String color, int maxSpeed) {
		super();
		this.brand = brand;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}
	

}


实现类:


package com.zhushuai.reflect;

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

public class ReflectDemo {

	/**
	 * @param args
	 * @throws ClassNotFoundException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 * @throws SecurityException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
		// TODO Auto-generated method stub
		Class cl = Class.forName("com.zhushuai.domain.Car");
		Object obj = cl.newInstance();
		
		Method mSetBrand = cl.getDeclaredMethod("setBrand", String.class);
		Method mGetBrand= cl.getDeclaredMethod("getBrand");
		mSetBrand.invoke(obj, "Audi");
		String brandStr = (String)mGetBrand.invoke(obj, null);
		
		Method mSetcolor = cl.getDeclaredMethod("setColor", String.class);
		Method mGetcolor = cl.getDeclaredMethod("getColor");
		mSetcolor.invoke(obj, "red");
		String colorStr = (String)mGetcolor.invoke(obj, null);
		
		Method mSetMaxSpeed = cl.getDeclaredMethod("setMaxSpeed", int.class);
		Method mGetMaxSpeed = cl.getDeclaredMethod("getMaxSpeed");
		mSetMaxSpeed.invoke(obj, 360);
		int maxSpeedStr = (Integer)mGetMaxSpeed.invoke(obj, null);
		
		
		System.out.println("Brand:"+brandStr+"\n"+"Color"+colorStr+"\n"+"MaxSpeed"+maxSpeedStr);
	}

}


结果:




总结技巧:


一、JAVA反射的常规使用步骤

    反射调用一般分为4个步骤:

  • 得到要调用类的class
  • 创建要调用类的newinstance
  • 得到要调用的类中的方法(Method)
  • 方法调用(invoke)

二、方法调用中的参数类型

        在方法调用中,参数类型必须正确,这里需要注意的是不能使用包装类替换基本类型,比如不能使用Integer.class代替int.class。

       如我要调用Car的setMaxSpeed方法,下面的调用是正确的:


Method mSetMaxSpeed = cl.getDeclaredMethod("setMaxSpeed", int.class);

而如果我们用Integer.class替代int.class就会出错,如:


Method mSetMaxSpeed = cl.getDeclaredMethod("setMaxSpeed", Integer.class);

三、static方法的反射调用

 

       static方法调用时,不必得到对象示例,如下:


Class cls = Class.forName("chb.test.reflect.Student");
Method staticMethod = cls.getDeclaredMethod("hi",int.class,String.class);
staticMethod.invoke(cls,20,"chb");//这里不需要newInstance
//staticMethod.invoke(cls.newInstance(),20,"chb");<pre></pre>

四、private的成员变量赋值

    如果直接通过反射给类的private成员变量赋值,是不允许的,这时我们可以通过setAccessible方法解决。代码示例:


Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();//得到一个实例
Field field = cls.getDeclaredField("age");
field.set(student, 10);
System.out.println(field.get(student));

运行如上代码,系统会报出如下异常:


java.lang.IllegalAccessException: Class chb.test.reflect.TestClass can not access a member of class chb.test.reflect.Student with modifiers "private"

解决方法:


Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();
Field field = cls.getDeclaredField("age");
field.setAccessible(true);//设置允许访问
field.set(student, 10);
System.out.println(field.get(student));

其实,在某些场合下(类中有get,set方法),可以先反射调用set方法,再反射调用get方法达到如上效果,代码示例:


Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();

Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
setMethod.invoke(student, 15);//调用set方法
			
Method getMethod = cls.getDeclaredMethod("getAge");
System.out.println(getMethod.invoke(student));//再调用get方法



参考文章: http://blog.csdn.net/hbcui1984/article/details/2719089#




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值