Java 反射机制

什么是反射:

对于任何一个类,我们都能知道他有哪些方法。对于任何一个对象我们都可以调用他的任意一个方法和属性,这种动态的获取信息以及动态的调用对象的方法就称为java的反射机制。形象一点说,任何一个类或者对象,对我们来说都是透明的,想要啥直接拿就可以。


首先列出我们要反射的类:
public class Person {
	
	int age;
	String name;
	private String email;
	
	public Person(int age, String name) {
		this.age = age;
		this.name = name;
	}
	
	public Person(int age){};
	public Person(){};
	
	
	private String getEmail() {
		System.out.println("我是getEmail");
		return email;
	}

	private void setEmail(String email) {
		this.email = email;
	}
	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		System.out.println("我是setName");
		this.name = name;
	}
	
}
要想对一个类进行反射,就必须获取他的字节码字节码。有三种形式:
        //第一种
    	Class<?> c1 =new Person().getClass();
    	//第二种
    	Class<?> c2 = Person.class;
    	//第三种,要加包名
    	try {
			Class<?> c3 = Class.forName("one.Person");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
通过反射获取类中的所有构造器
        //获取类中的所有构造器
    	Constructor<?>[] con = c1.getConstructors();
    	System.out.println("共"+con.length+"构造器");
    	for (int i = 0; i < con.length; i++) {
    		System.out.println("第"+i+"个构造参数");
    		//获取构造器参数类型
			Class[] paramenter = con[i].getParameterTypes();
			for (int j = 0; j < paramenter.length; j++) {
				//打印构造器参数
				System.out.print(paramenter[j].getName()+"   ");
			}
			System.out.println();
		}

结果如下:

共3构造器
第0个构造参数

第1个构造参数
int   
第2个构造参数
int   java.lang.String   

一个无参,还有两个有参构造。


通过获取的构造器进行实例化
    try {
    		Person per1 = (Person) con[0].newInstance();
    		Person per2 = (Person) con[1].newInstance(20);
    		Person per3 = (Person) con[2].newInstance(19,"lv");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

通过反射获取类中的属性
Person per1 = null,per2 = null,per3= null;
    	try {
    		 per1 = (Person) con[0].newInstance();
    		 per2 = (Person) con[1].newInstance(20);
    		 per3 = (Person) con[2].newInstance(19,"lv");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
    	
    	//获取某个对象内的某个字段
    	try {
			Field f = c1.getDeclaredField("email"); //或取私有属性
			//对私有字段的访问取消检查
			f.setAccessible(true);
			//修改该对象的emal字段
			f.set(per3, "emal@qq.com");
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	
    	//获取当前类的所有属性类型和值
    	Field[] field = c1.getDeclaredFields();
    	//对私有字段的访问取消检查
    	Field.setAccessible(field, true);
    	for (int i = 0; i < field.length; i++) {
			try {
				System.out.println("属性名:"+field[i].getName()+"属性类型:"
						+field[i].getType()+"属性值:"+field[i].get(per3));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

结果如下:

属性名:age属性类型:int属性值:19
属性名:name属性类型:class java.lang.String属性值:lv
属性名:email属性类型:class java.lang.String属性值:emal@qq.com

注意:取消安全性检查后才可以访问私有属性


通过反射获取类中的方法并运行
        //获取全部方法
    	Method[] methods = c1.getDeclaredMethods();
    	for (int i = 0; i < methods.length; i++) {
			System.out.println("方法名称:"+methods[i].getName()+
					" 返回值类型 :"+methods[i].getReturnType()+
					" 方法参数:"+methods[i].getParameterTypes());
			
		} 
    	
    	//获取无参私有方法
    	try {
			Method method = c1.getDeclaredMethod("getEmail");
			//对私有字段取消安全检查
			method.setAccessible(true);
			System.out.println("私有方法名称:"+method.getName()+" 返回值类型:"
			+method.getReturnType().getName());
			//调用无参的私有方法
			method.invoke(per3);//即getEmail方法
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	//获取有参方法
    	try {
			Method meth = c1.getDeclaredMethod("setName", String.class);
			//调用有参方法
			meth.invoke(per3, "我是Name");//即setName方法
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
    	

结果如下:

方法名称:main 返回值类型 :void 方法参数:[Ljava.lang.Class;@6d06d69c
方法名称:getName 返回值类型 :class java.lang.String 方法参数:[Ljava.lang.Class;@7852e922
方法名称:setName 返回值类型 :void 方法参数:[Ljava.lang.Class;@4e25154f
方法名称:setEmail 返回值类型 :void 方法参数:[Ljava.lang.Class;@70dea4e
方法名称:getAge 返回值类型 :int 方法参数:[Ljava.lang.Class;@5c647e05
方法名称:setAge 返回值类型 :void 方法参数:[Ljava.lang.Class;@33909752
方法名称:getEmail 返回值类型 :class java.lang.String 方法参数:[Ljava.lang.Class;@55f96302
私有方法名称:getEmail 返回值类型:java.lang.String
我是getEmail
我是setName

总结一下:
这些 只是最基本的反射,更多的使用方法还是需要去查api。其实反射是非常重要的。我们还是有必要去掌握它。

若有错误,还请指出,谢谢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tʀᴜsᴛ³⁴⁵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值