JAVA笔记:深入研究Java中的反射机制

反射机制

在正常情况下,Java中必须知道一个类的完整路径之后才能实例化对象,但是也允许通过对象来查找类,这就是Java中Class类的功能,如下实例:
package org.lxh.demo15.getclassdemo ;
class X{
};
public class GetClassDemo01{
	public static void main(String args[]){
		X x = new X() ;	// 实例化X类的对象
		System.out.println(x.getClass().getName()) ;	// 得到对象所在的类
	}
};

反射机制的优点与缺点 

为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,静态编译:在编译时确定类型,绑定对象,即通过。 
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。     
 一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。
比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。         
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。 

Class类

Class类表示一个类的本身,通过Class类可以完整的得到一个类的完整结构,包括此类中的方法定义,属性定义等。
实例化Class对象:
package org.lxh.demo15.getclassdemo ;
class X{
};
public class GetClassDemo02{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 指定泛型
		Class<?> c2 = null ;		// 指定泛型
		Class<?> c3 = null ;		// 指定泛型
		try{
			// 以下的操作形式是在开发中最常用的一种形式
			c1 = Class.forName("org.lxh.demo15.getclassdemo.X") ;
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		c2 = new X().getClass() ;		// 通过Object类中的方法实例化
		c3 = X.class ;	// 通过类.class实例化
		System.out.println("类名称:" + c1.getName())  ;	// 得到类的名称
		System.out.println("类名称:" + c2.getName())  ;	// 得到类的名称
		System.out.println("类名称:" + c3.getName())  ;	// 得到类的名称
	}
};

注意:被实例化对象的类中必须存在无参构造方法,如果不存在则无法实例化。
如果想要调用有参构造进行对象的实例化操作,则必须使用Constructor类完成,此类表示构造方法,并通过可变参数传递要求的内容。

反射应用:取得类的结构

反射的功能:
*可以使用反射取得实现的全部接口
*可以使用反射取得一个类所继承的父类
*可以使用反射取得一个类的全部构造方法
*可以使用反射取得一个类的全部方法
*可以使用反射取得一个类中的全部属性

取得属性:
package org.lxh.demo15.classinfodemo ;
import java.lang.reflect.Field ;	// 导入构造方法的包
import java.lang.reflect.Modifier ;	// 导入构造方法的包
public class GetFieldDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		{	// 本类属性
			Field f[] = c1.getDeclaredFields() ;	// 取得本类中的属性
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType() ;	// 得到属性类型
				int mo = f[i].getModifiers() ;	// 得到修饰符的数字
				String priv = Modifier.toString(mo) ; // 还原修饰符
				System.out.print("本类属性:") ;
				System.out.print(priv + " ") ;	
				System.out.print(r.getName() + " ") ;	// 得到属性类型
				System.out.print(f[i].getName()) ;	// 输出属性名称
				System.out.println(" ;") ;
			}
		}
		{	// 公共属性
			Field f[] = c1.getFields() ;	// 取得本类中的公共属性
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType() ;	// 得到属性类型
				int mo = f[i].getModifiers() ;	// 得到修饰符的数字
				String priv = Modifier.toString(mo) ; // 还原修饰符
				System.out.print("公共属性:") ;
				System.out.print(priv + " ") ;	
				System.out.print(r.getName() + " ") ;	// 得到属性类型
				System.out.print(f[i].getName()) ;	// 输出属性名称
				System.out.println(" ;") ;
			}
		}
	}
};


取得接口:
package org.lxh.demo15.classinfodemo ;
public class GetInterfaceDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Class<?> c[] = c1.getInterfaces() ;	// 以数组形式返回实现的全部接口
		for(int i=0;i<c.length;i++){
			System.out.println("实现的接口名称:" + c[i].getName()) ;	// 输出接口名称
		}
	}
};


取得方法:
package org.lxh.demo15.classinfodemo ;
import java.lang.reflect.Method ;	// 导入构造方法的包
import java.lang.reflect.Modifier ;	// 导入构造方法的包
public class GetMethodDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Method m[] = c1.getMethods() ;	// 取得全部方法
		for(int i=0;i<m.length;i++){
			Class<?> r = m[i].getReturnType() ;	// 得到返回值类型
			Class<?> p[] = m[i].getParameterTypes() ;	// 取得全部参数的类型
			int xx = m[i].getModifiers() ;	// 得到修饰符
			System.out.print(Modifier.toString(xx) + " ") ;	// 输出修饰符
			System.out.print(r + " ") ;
			System.out.print(m[i].getName()) ;
			System.out.print("(") ;
			for(int j=0;j<p.length;j++){
				System.out.print(p[j].getName() + " " + "arg" + j) ;
				if(j<p.length-1){
					System.out.print(",") ;
				}
			}
			Class<?> ex[] = m[i].getExceptionTypes() ;	// 取出异常
			if(ex.length>0){
				System.out.print(") throws ") ;
			}else{
				System.out.print(")") ;
			}
			for(int j=0;j<ex.length;j++){
				System.out.print(ex[j].getName()) ;
				if(j<p.length-1){
					System.out.print(",") ;
				}
			}
			System.out.println() ;
		}
	}
};


取得全部父类:
package org.lxh.demo15.classinfodemo ;
public class GetSuperClassDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Class<?> c2 = c1.getSuperclass() ;	// 取得父类
		System.out.println("父类名称:" + c2.getName()) ;
	}
};

通过反射机制,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。

调用属性:
package org.lxh.demo15.invokedemo ;
import java.lang.reflect.Field ;
public class InvokeFieldDemo{
	public static void main(String args[]) throws Exception{
		Class<?> c1 = null ;
		Object obj = null ;
		c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化Class对象
		obj = c1.newInstance() ;
		Field nameField = null ;
		Field ageField = null ;
		nameField = c1.getDeclaredField("name") ;	// 取得name属性
		ageField = c1.getDeclaredField("age") ;	// 取得name属性
		nameField.setAccessible(true) ;	// 此属性对外部可见
		ageField.setAccessible(true) ;	// 此属性对外部可见
		nameField.set(obj,"哈哈") ;	// 设置name属性内容
		ageField.set(obj,10) ;			// 设置age属性内容
		System.out.println("姓名:" + nameField.get(obj)) ;
		System.out.println("年龄:" + ageField.get(obj)) ;
	}
};

调用setter和getter方法:
package org.lxh.demo15.invokedemo ;
import java.lang.reflect.Method ;
public class InvokeSetGetDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;
		Object obj = null ;
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化Class对象
		}catch(Exception e){}
		try{
			obj = c1.newInstance() ;
		}catch(Exception e){}
		setter(obj,"name","李兴华",String.class) ;	// 调用setter方法
		setter(obj,"age",30,int.class) ;	// 调用setter方法
		System.out.print("姓名:") ;
		getter(obj,"name") ;
		System.out.print("年龄:") ;
		getter(obj,"age");
	}
	/**
		Object obj:要操作的对象
		String att:要操作的属性
		Object value:要设置的属性内容
		Class<?> type:要设置的属性类型
	*/
	public static void setter(Object obj,String att,Object value,Class<?> type){
		try{
			Method met = obj.getClass().getMethod("set"+initStr(att),type) ;	// 得到setter方法
			met.invoke(obj,value) ;	// 设置setter的内容
		}catch(Exception e){
			e.printStackTrace() ;
		}
	}
	public static void getter(Object obj,String att){
		try{
			Method met = obj.getClass().getMethod("get"+initStr(att)) ;	// 得到setter方法
			System.out.println(met.invoke(obj)) ;	// 调用getter取得内容
		}catch(Exception e){
			e.printStackTrace() ;
		}
	}
	public static String initStr(String old){	// 将单词的首字母大写
		String str = old.substring(0,1).toUpperCase() + old.substring(1) ;
		return str ;
	}
};











你可能感兴趣的:(JAVA笔记:深入研究Java中的反射机制)