Java反射

定义

在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法(任何权限);对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射机制的作用:

  • 在运行中分析类的能力
  • 在运行中查看对象
  • 实现通用的数组代码

Class类

获取CLass实例:

  1. Object类中的getClass方法会返回一个Class类型的实例
    例如:Class cl =user.getClass()
    getName方法:返回类的名字,例如下面的语句:
cl.getName();

输出的是:com.sendi.entity.User

2.forName(String)方法:获得类名对应的CLass对象,例如

String className="com.sendi.entity.User";
Class cl=Class.forName(className);

3.T.class:

		Class cl1=int.class;
		Class cl2=double.class;

4.创建对象
newInstance()方法:可以方便快捷地创建一个对象出来,例如:

User user3=u.getClass().newInstance();

如果构造器有参数,则需要使用Constructor类中的newInstance方法。

getFields方法:返回Field数组
getMethods方法:返回Method数组
getConstructors方法:返回Constructor数组

getDeclareFields方法:返回类中声明的全部域
getDeclareMethods方法:返回类中声明的全部方法
getDeclareConstructors方法:返回Constructor

setAccessible(true);//设置访问权限

其中包括私有的和受保护的成员,但不包括超类。

利用反射分析类的能力

在java.lang.reflex包中有三个类:Field、Method和Constructor,他们分别用于描述类的域、方法、构造器。他们都有一个getName的方法,用来返回项目的名称。

  • Field类:
    提供public域
    getModifiers():返回一个整形数值,可供Modifiers.toString方法分析出修饰符
  • Method类:
    提供方法
    getModifiers():返回一个整形数值,可供Modifiers.toString方法分析出修饰符
    Class getReturnType():返回方法返回的类型
  • Constructor类:
    提供构造器
    getModifiers():返回一个整形数值,可供Modifiers.toString方法分析出修饰符
    Class getDeclaringClass():返回一个描述类中定义的构造器、方法或域的Class对象。
    Class[] getParameterTypes():返回描述构造器参数类型数组。

例子,分析类中的所有成员:

public class Demo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String name;
		if(args.length>0)name=args[0];
		else{
			Scanner in=new Scanner(System.in);
			System.out.println("enter class name(e.g.java.util.Date)");
			name=in.next();
		}
		
		try {
			Class cl=Class.forName(name);
			Class superCl=cl.getSuperclass();
			String modifiers=Modifier.toString(cl.getModifiers());
			
			if(modifiers.length()>0)System.out.print(modifiers+" ");
			System.out.print("class "+name);
			
			if (superCl!=null && superCl!=Object.class) 
				System.out.print(" extends "+superCl.getName());
			
			System.out.print("\n{\n");
			printConstuctors(cl);
			System.out.println();
			printMethods(cl);
			System.out.println();
			printFields(cl);
			System.out.println("}");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		System.exit(0);

	}

	private static void printFields(Class cl) {
		// TODO Auto-generated method stub
		Field[] fields=cl.getDeclaredFields();
		
		for (Field field : fields) {
			Class type=field.getType();
			String name=field.getName();
			
			System.out.print(" ");
			String modifiers=Modifier.toString(field.getModifiers());
			
			if(modifiers.length()>0)System.out.print(modifiers+" ");
			
			System.out.println(type.getName()+" "+name+";");
		}
	}
/**
 * 打印方法
 * @param cl
 */
	private static void printMethods(Class cl) {
		// TODO Auto-generated method stub
		Method[] methods=cl.getMethods();
		for (Method method : methods) {
			Class retType=method.getReturnType();
			String name=method.getName();
			
			System.out.print("  ");
			
			String modifiers=Modifier.toString(method.getModifiers());
			if(modifiers.length()>0)System.out.print(modifiers+" ");
			System.out.print(retType.getName()+" "+name+"(");
			
			Class[] paramType=method.getParameterTypes();
			for(int i=0;i<paramType.length;i++){
				if(i>0)System.out.print(", ");
				System.out.print(paramType[i].getName());
			}
			System.out.println(");");
			
		}
	}
/**
 * 打印构造方法
 * @param cl
 */
	private static void printConstuctors(Class cl) {
		// TODO Auto-generated method stub
		Constructor[] constructors=cl.getConstructors();
		for (Constructor constructor : constructors) {
			String name=constructor.getName();
			System.out.print("   ");
			String modifiers=Modifier.toString(constructor.getModifiers());
			if(modifiers.length()>0)System.out.print(modifiers+" ");
			System.out.print(name+"(");
			
			//参数
			Class[] paramTypes=constructor.getParameterTypes();
			for(int i=0;i<paramTypes.length;i++){
				if(i>0)System.out.print(", ");
				System.out.print(paramTypes[i].getName());
			}
			System.out.println(")");
		}
	}

}

动态代理的应用

	##主题接口
	interface Suject {
    	fun request()
	}

	##真正的主题
	class RealSubject : Suject {
	    override fun request() {
	        println("real subject")
	    }
	}

   ##InvocationHandler
   class ProxyHandler(val subject: Suject) : InvocationHandler {
    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
        println("before-------------")

        println("call fun: ${method?.name}")
        val obj = method?.invoke(subject)//调用真正主题的方法

        println("after-------------")

        return obj
    }
}

##使用
	fun main(args: Array<String>) {
	    //创建目标对象
	    val realSubject = RealSubject()
	    //创建调用处理器
	    val handler = ProxyHandler(realSubject)
	
	    //动态生成代理对象
	    val proxySubject = Proxy.newProxyInstance(RealSubject::class.java.classLoader,
	            RealSubject::class.java.interfaces,
	            handler) as Suject
	
	    proxySubject.request()
	
	}

打印结果:

before-------------
call fun: request
real subject
after-------------

小总结
在动态代理实现中,无需编写代理类,而是在运行时生成一个代理类,并且调用对应方法的时候可以添加其他的逻辑,使程序更灵活。

在运行时使用反射

Field类中的get方法:获取该域的当前值,例如:

User user=new User("asendi",11);
		Class cl=user.getClass();
		Field f01=cl.getDeclaredField("name");//name域
		f01.setAccessible(true);//设置访问权限
		Object obj=f01.get(user);
		System.out.println(obj.toString());

打印结果是:asendi
注意: 当name是私有时,则必须加f01.setAccessible(true)来设置访问权限。
Field类中的set方法:用来设置当前域的值,例如:

Field f02=cl.getDeclaredField("age");//age域
			f02.setAccessible(true);
			Integer age=f02.getInt(user);
			System.out.println("before:"+age);
			
			f02.set(user, 22);
			Integer age2=f02.getInt(user);
			System.out.println("after:"+age2);

输出结果是:

			before:11
			after:22

java.lang.reflect.Array

Object get(Object array,int index):返回指定数组对象中索引的值。

void set(Object array,int index):给指定数组对象中索引的对象指定新值。

int getLength(Object array):返回指定数组的长度。

Object newInstance(Class componentType,int length):返回一个具有给定类型,给定长度的新数组。

Object newInstance(Class componentType,int… length):创建具有指定组件类型和维度的新数组。

下面给出一个数组拷贝的方法:

public static Object goodCopyOf(Object a,int newLength){
		Class cl=a.getClass();
		if(!cl.isArray())return null;
		Class componentType=cl.getComponentType();
		
		int length=Array.getLength(a);
		Object newArray=Array.newInstance(componentType, newLength);
		
		System.arraycopy(a, 0, newArray, 0, Math.max(newLength, length));//拷贝数组
		
		
		return newArray;
	}

调用方法

获取Method方法,例如:

Method m=User.class.getMethod("getAge");

invoke(Object obj,Object… paramenters):调用这个对象所描述的方法,并返回该方法的返回值。例如:

User u=new User("sendi",20);
		Method m=User.class.getMethod("getAge");
		int age=(Integer) m.invoke(u);
		System.out.println("age::"+age);

打印结果:age::20

关于放射的基础和应用介绍这么多,它还有很多方法和功能,总的来说它可以在运行时去决定逻辑,使程序更加灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值