java反射

反射的作用,参考http://blog.youkuaiyun.com/ritterliu/article/details/7764849


下面介绍几个反射的用法:

1.Class的对象获取

package com.note;
/*
 * 在java的世界里,万事万物皆是对象。两个不是:普通变量,和静态成员
 * 
 * 一般类是java.lang.Class的对象:Class构造方法是私有的,所以不能new Class();
 */
public class ClassDemo {
	public static void main(String [] args) {
		Foo foo1 =new Foo();
	 //Class实例对象,3种表示方式;
		
		//1.第一种。实际告诉我们任何一个类都有一ig隐含的静态成员变量claas
		Class c1= Foo.class;
		
		//2.第二种。已知该类的对象
		 Class c2 =foo1.getClass();
		 
		 //3.第三种:属于动态加载类型。编译时加载类就是静态,运行时加载是动态
		 //new都是静态加载类,全部正确且存在才能编译通过。而动态加载不需要 
		 Class c3= null;
		 try {
			c3= Class.forName("com.note.Foo");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 //官网:c1,c2表示了Foo类的类类型
		 
		 
		//结果均为true
		 System.out.println(c1==c2);
		 System.out.println(c3==c2);
		 
		 
		 //我们可以通过类 的类类型创建该类的对象实例-----》通过c1/c2/c3创建Foo的实例
		 //c1是什么类类型,就创建什么类的实例,需要强制转换,和抛出异常
		 try {
			Foo foo =(Foo)c1.newInstance();
			foo.print();
		} catch (InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	
}
//不能用public修饰
class Foo{
	void print(){
		System.out.println("foo");
	}
}


2.Class.forName(str)的区别

public class ClassDemo1 {
	public static void main(String[] args){
		
		try{
			//动态加载,编译能通过,运行时才加载类
			Class c = Class.forName("args[0]");
			//officeAble是一个接口,WORD和excel实现了这个接口,
			//所以不管c为word还是excel都能正确创建下面对象
			OfficeAble oa = (OfficeAble)c.newInstance();
			oa.print();
		}catch(Exception e){
			
		}
		
	}

}

3.通过反射获取一个类的成员变量、方法、构造函数:

package com.note;

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

//获取类的全部信息
public class ClassUtil {
	String s1;
	int i1;
	
	public static void main(String[] args) {
	Class c0 = int.class;
	Class c2 = String.class;
	//就是void也是类 ,皆是类	
//	Class c3 = void.class;
//	
//	System.out.println(c0.getName());
//	System.out.println(c2.getName());
//	//不含包名的名称
//	System.out.println(c2.getSimpleName());
//	System.out.println(c3.getName());
//	
	
	//调用下面方法,打印类的成员函数	
	String s="hello";
	
		ClassUtil.printClassMessage_Methods(new ClassUtil());
		ClassUtil.printClassMessage_Fields(new ClassUtil());
		ClassUtil.printClassMessage_Constructor(s);
	}
	/*
	 * 打印类的信息,包括类的成员函数、成员变量	
	 *  
	 */
	
	public static void printClassMessage_Methods(Object obj){
		
		//1.首先获取类类型
		Class c = obj.getClass();
		//2.获取类的名称
		System.out.println("类的名称:"+c.getName());
		/*
		 * Method类。方法对象
		 * 一个成员方法就是iyi个Method当对象
		 * getMethod()方法获取的是所有的public函数,包括父类继承的
		 * getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
		 */
		
		Method[] ms=c.getMethods();//c.getDeclaredMethods()
		for(int i=0;i<ms.length;i++){
			//得到方法的返回值类型的类类型
			Class returnType = ms[i].getReturnType();
			System.out.print(returnType.getName()+" ");
			//得到方法的名称
			System.out.print(ms[i].getName()+"(");
			//获取参数类型----》	得到的参数列表的类型的类类型
			Class[] paramTypes = ms[i].getParameterTypes();
			for(Class class1:paramTypes){
				System.out.print(class1.getName()+",");				
			}
			System.out.println(")");
	
			}
		}
		public static void printClassMessage_Fields(Object obj){
			
			/*
			 * 成员变量也是对象.java.lang.reflect.Field
			 * Field类封装了关于成员变量的操作
			 * getFileds()方法获取的是所有的public成员变量的信息
			 * getDeclaredFields()获取的是该类自己声明的成员变量的信息
			 */
			Class c = obj.getClass();
			Field[] fs= c.getDeclaredFields();
			for(Field field:fs){
				//得到成员变量的类类型
				Class fieldType = field.getType();
				System.out.print(fieldType.getName()+" ");
				//得到成员变量的名字
				System.out.println(field.getName());
								
			}
		}
		
		//获取对像的构造函数信息
		public  static void printClassMessage_Constructor(Object obj){
			
			Class c= obj.getClass();
			/*
			 * 构造函数也是对象
			 * java.lang.Construtor中封装了构造函数的信息
			 * getConstruts()获取所有的public的构造函数
			 * getDeclaredConstruts的得到自己声明的构造函数
			 * 
			 */
			Constructor[] cs = c.getDeclaredConstructors();
			for(Constructor constructor:cs){
				
				System.out.print(constructor.getName()+"(");
				
				//得到参数类型
				Class paramTypes[] = constructor.getParameterTypes();
				for(Class class1:paramTypes){
					System.out.print(class1.getName()+",");
				}
				System.out.println(")");
			}
		}
	

}


4.方法的反射:

package com.note;

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

/*
 * 方法的反射:
 *  * 1.获取方法
 *  2.通过方法反射
 */
public class ClassInvoke {
	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		//要获取print(int,int)方法
		A a1 = new A();
		//获取方法 名称和参数列表来决定c.getMethod(name,Class... parameters)
		Class c = a1.getClass();
		//此处会抛出异常,方法不存在或者
		try {
			//Method m = c.getMethod("print",int.class,int.class);也可以
			Method m = c.getMethod("print",new Class[]{int.class,int.class});
			
			//方法的反射操作
			//a1.print(10,20);方法的反射操作是用m对象来进行方法调用和a1.print调用的效果
			//方法有返回值返回返回值,没有返回值返回void
			Object o=m.invoke(a1, new Object[]{10,20});//(a1, 10,20);
			
			
			System.out.println("============");
			
			A a2= new A();
			Class c1 =a2.getClass();
			Method m1 = c1.getMethod("print",String.class,String.class);
			m1.invoke(a2,"ss","BBB");
			
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

class A{
	public void print(int a ,int b){
		System.out.println(a+b);
	}
	public void print(String a ,String b){
		System.out.println(a.toUpperCase()+","+b.toLowerCase());
	}
}

5.反射绕过编译。都是在编译之后

package com.note;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
//泛型问题。ArrayList<String>为泛型
public class ClassMethod {
	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		ArrayList  list1 = new ArrayList ();	
		ArrayList<String> list2 = new ArrayList<String>();		
		
		
		Class c1 = list1.getClass();
		Class c2= list2.getClass();
		//结果为TRUE
		System.out.println(c1==c2);
		
		/*
		 * 	集合的泛型是防止错误输入的,只在编译阶段有效,即不能在list2中插入部位String类型的
		 *反射是的操作都是编译之后的操作
		 *c1=c2,表明集合的泛型都是在编译阶段有效
		 *我们可以通过方法的反射绕过编译
		 */
		
		try {
			Method m = c2.getMethod("add",Object.class);
			m.invoke(list1,20);
			System.out.println(list1);
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值