JAVA反射

一、Java反射的概念

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

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象

 

二、反射的使用

获取class对象的三种方法:

  1.  Object ——> getClass(); 
  2. 任何数据类型(包括基本数据类型)都有一个“静态”的class属性 
  3.  通过Class类的静态方法:forName(String  className)(常用) 

在运行期间,一个类,只有一个Class对象产生。

三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。

 

定义一个类供我们反射获取

package java_reflect;

import java.io.Serializable;

public class UserBean implements Serializable {
	
	public UserBean(){
		System.out.println("无参构造");
	}
	
	public UserBean(String username){
		System.out.println("有参构造(username)="+username);
	}
	
	private UserBean(int id){
		System.out.println("private有参构造(id)="+id);
	}
	
	public UserBean(int id,String username){
		System.out.println("有参构造(id,username)="+id+"~"+username);
	}
	
	public String aString;
	private int id;
	private String username;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
		System.out.println("username="+username);
	}
	
	public String getResult(){
		return "结果";
	}
	private void testMethod(String message){
		System.out.println("testMethod(String)");
	}
}

1、获取类的class对象

try {  
    Class userClass = Class.forName("java_reflect.UserBean");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名   
} catch (ClassNotFoundException e) {  
    e.printStackTrace();  
}  

2、构造器的获取和运行

通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;  
1.批量的方法: 
         public Constructor[] getConstructors():所有”公有的”构造方法 
         public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有) 

2.获取单个的方法,并调用: 
         public Constructor getConstructor(Class… parameterTypes):获取单个的”公有的”构造方法: 
         public Constructor getDeclaredConstructor(Class… parameterTypes):获取”某个构造方法”可以是私有的,或受保护、默认、公有; 
      
调用构造方法: 
         Constructor–>newInstance(Object… initargs) 

暴力访问(忽略掉访问修饰符)

         Constructor–>setAccessible(true);

private static void getConstructor1() throws ClassNotFoundException {
		Class class1 = Class.forName("java_reflect.UserBean");
		
		System.out.println("===========获取所有公有构造方法=============");
		Constructor[] constructor = class1.getConstructors();
		for (Constructor obj : constructor) {
			System.out.println(obj);
		}

		System.out.println("==========所有的构造方法(包括:私有、受保护、默认、公有)==============");
		Constructor[] constructor2 = class1.getDeclaredConstructors();
		for (Constructor obj : constructor2) {
			System.out.println(obj);
		}
	}

private static void RunConstructor() throws Exception {
		Class class1 = Class.forName("java_reflect.UserBean");
		
		System.out.println("===========运行公有无参构造方法=============");
		Constructor constructor = class1.getConstructor(null);//因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型 
		constructor.newInstance();
		
		System.out.println("===========运行公有有参构造方法=============");
		Constructor constructor2 = class1.getConstructor(String.class);
		constructor2.newInstance("jerry");
		
		System.out.println("===========运行公有多参构造方法=============");
		Constructor constructor3=class1.getConstructor(int.class,String.class);
		constructor3.newInstance(1,"jerry");
		
		System.out.println("===========运行私有有参构造方法=============");
		Constructor constructor4=class1.getDeclaredConstructor(int.class);
		constructor4.setAccessible(true);//暴力访问(忽略掉访问修饰符)
		constructor4.newInstance(2);		
	}

3、成员变量的获取和赋值

1.批量的 
     Field[] getFields():获取所有的”公有字段” 
     Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有; 
2.获取单个的: 
     public Field getField(String fieldName):获取某个”公有的”字段; 
     public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的) 

设置字段的值: 
    Field –> public void set(Object obj,Object value): 
                参数说明: 
                1.obj:要设置的字段所在的对象; 
                2.value:要为字段设置的值

/暴力反射,解除私有限定

    Field –> setAccessible(true);

private static void getField1()throws Exception{
		Class class1 = Class.forName("java_reflect.UserBean");
		
		System.out.println("==========所有的公有成员变量==============");
		Field[] fields=class1.getFields();
		for(Field f:fields){
			System.out.println(f);
		}
		
		System.out.println("==========所有成员变量(包括:私有、受保护、默认、公有)==============");
		Field[] fields2=class1.getDeclaredFields();
		for(Field f:fields2){
			System.out.println(f);
		}
	}
	
	private static void setField1()throws Exception{
		Class class1 = Class.forName("java_reflect.UserBean");
		
		System.out.println("==========获取公有成员变量并赋值==============");
		Field field1=class1.getField("aString");
		Object object=class1.newInstance();//生产对象
		field1.set(object, "aaa");//将aaa赋值给成员变量aString
		UserBean userBean=(UserBean)object;
		System.out.println(userBean.aString);//验证
		
		System.out.println("==========获取私有成员变量并赋值==============");
		Field field2=class1.getDeclaredField("username");
		Object object2=class1.newInstance();
		field2.setAccessible(true);//暴力反射,解除私有限定 
		field2.set(object2, "jerry");
		UserBean userBean2=(UserBean)object2;
		System.out.println(userBean2.getUsername());//验证
	}

4、方法的获取和执行

1.批量的: 
    public Method[] getMethods():获取所有”公有方法”;(包含了父类的方法也包含Object类) 
    public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的) 
2.获取单个的: 
    public Method getMethod(String name,Class<?>… parameterTypes): 
                参数: 
                    name : 方法名; 
                    Class … : 形参的Class类型对象 
    public Method getDeclaredMethod(String name,Class<?>… parameterTypes) 
    
 调用方法: 
    Method –> public Object invoke(Object obj,Object… args): 
                参数说明: 
                obj : 要调用方法的对象; 
                args:调用方式时所传递的实参;

暴力反射

    Method –> setAccessible(true);

private static void getMethod1()throws Exception{
		Class class1 = Class.forName("java_reflect.UserBean");
		
		System.out.println("==========获取所有公有方法(包含了父类的方法也包含Object类)==============");
		Method[] methods= class1.getMethods();
		for(Method method:methods){
			System.out.println(method);
		}
		
		System.out.println("==========获取所有方法,包括私有的(不包括继承的)==============");
		Method[] methods1= class1.getDeclaredMethods();
		for(Method method:methods1){
			System.out.println(method);
		}
	}
	
	private static void runMethod1()throws Exception{
		Class class1 = Class.forName("java_reflect.UserBean");
		
		System.out.println("==========获取公有方法,并运行拿到返回值==============");
		Method method=class1.getMethod("getResult", null);
		Object obj=class1.newInstance();//生产对象
		Object result=method.invoke(obj, null);//调用方法
		System.out.println("返回值="+result);//验证方法返回值
		
		System.out.println("==========获取公有方法,传值并运行拿到返回值==============");
		Method method2=class1.getMethod("setUsername", String.class);
		Object obj2=class1.newInstance();//生产对象
		Object result2=method2.invoke(obj2, "jerry");//调用方法
		System.out.println("返回值="+result2);//验证方法返回值(void返回值为null)
		
		System.out.println("==========获取私有方法,并运行拿到返回值==============");
		Method method3=class1.getDeclaredMethod("testMethod", String.class);
		method3.setAccessible(true);
		Object obj3=class1.newInstance();//生产对象
		Object result3=method3.invoke(obj3, "参数信息");//调用方法
		System.out.println("返回值="+result3);//验证方法返回值
	}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值