Java 反射

为什么要反射?

  • 通过反射技术读取.class文件
  • JVM底层用了大把的反射,获取你定义的类中的数据。SSM框架底层也用了大把反射
  • 作用:可以获取定义到任何定义的信息(包括成员变量,成员方法,构造器等)并且可以操作类的字段,方法,构造器等部分

反射的使用

  • 源码摘抄public final Class<T> extends Objectimplements Serializable
  • 反射Class类对象
    -Class.forName("类的圈路径")
    -类名.class
    -对象.getClass()
    
  • 常用方法
    获得包名、类名
    
    clazz.getPackage().getName()//包名
    
    clazz.getSimpleName()//类名
    
    clazz.getName()//完整类名
    
    !!成员变量定义信息
    
    getFields()//获得所有公开的成员变量,包括继承的变量
    
    getDeclaredFields()//获得本类定义的成员变量,包括私有,不包括继承的变量
    
    getField(变量名)
    
    getDeclaredField(变量名)
    
    !!构造方法定义信息
    
    getConstructor(参数类型列表)//获得公开的构造方法
    
    getConstructors()//获得所有公开的构造方法
    
    getDeclaredConstructors()//获得所有构造方法,包括私有
    
    getDeclaredConstructor(int.class, String.class)
    
    方法定义信息
    
    getMethods()//获得所有可见的方法,包括继承的方法
    
    getMethod(方法名,参数类型列表)
    
    getDeclaredMethods()//获得本类定义的方法,包括私有,不包括继承的方法
    
    getDeclaredMethod(方法名, int.class, String.class)
    
    反射新建实例
    
    c.newInstance();//执行无参构造
    
    c.newInstance(6, "abc");//执行有参构造
    
    c.getConstructor(int.class, String.class); //执行含参构造,获取构造方法
    
    反射调用成员变量
    
    c.getDeclaredField(变量名); //获取变量
    
    c.setAccessible(true); //使私有成员允许访问
    
    f.set(实例,); //为指定实例的变量赋值,静态变量,第一参数给 null
    
    f.get(实例); //访问指定实例的变量的值,静态变量,第一参数给 null
    
    反射调用成员方法
    
    获取方法
    
    Method m = c.getDeclaredMethod(方法名, 参数类型列表);
    
    m.setAccessible(true) ;//使私有方法允许被调用
    
    m.invoke(实例, 参数数据) ;//让指定的实例来执行该方法
    

    测试
    public class Student {
    		//提供构造
    		public Student() {}
    		public Student(String name, int age) {
    			this.name = name;
    			this.age = age;
    		}
    		
    		//提供属性
    		String name;
    		int age;
    		
    		//提供方法
    		public  void coding() {
    			System.out.println("coding...");
    		}
    	}
    
    获取Class对象
    		//获取Class对象
    		@Test  //测试方式:选中方法名-右键-Run as-Junit Test
    		public void classTest() throws Exception {
    			//?是泛型里的通配符,可以代表一切类型
    			Class<?> c = Class.forName("cn.tedu.reflection.Student");//参数是类的全路径--包名.类名
    			
    			Class<?> c2 = Student.class;
    			
    			Student s = new Student();
    			Class<?> c3 = s.getClass();
    			
    			System.out.println(c);
    			System.out.println(c2);
    			System.out.println(c3);
    		}
    
    获取构造方法
    	@Test  //获取构造方法
    	public void consTest() throws Exception {
    		//1,获取Class对象    ctrl  1自动补齐左面
    		Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
    		
    		//2,获取所有构造方法
    		Constructor<?>[] cs = clazz.getConstructors();
    		for (Constructor<?> c : cs) {
    			Class<?>[] ps = c.getParameterTypes();//获取构造方法的参数
    			System.out.println(  Arrays.toString(ps) );
    		
    			//获取构造方法名称cn.tedu.reflection.Student
    			System.out.println( c.getName() );
    		}
    	}
    
    获取成员方法
    	@Test  //获取成员方法
    	public void methodTest() throws Exception {	
    		//1,获取Class对象
    		Class<?> clazz = Student.class;
    		
    		//2,获取所有  公共的  成员方法
    		Method[] ms = clazz.getMethods();
    		for (Method m : ms) {
    			System.out.println( m.getName() );//包括继承自Object的所有方法
    		
    			Class<?>[] ps = m.getParameterTypes();//获取方法的参数
    			System.out.println( Arrays.toString(ps)  );
    		}
    	}
    
    获取成员变量  --  要求:变量都是公共的!!
    	@Test
    	public void filedTest() throws Exception {
    		//1,创建Class对象
    		//new Student() 这个对象没名字了,匿名对象
    		Class<?> clazz =new Student().getClass();
    		
    		//2,获取  公共的  成员变量  !!
    		Field[] fs = clazz.getFields();
    		for (Field f : fs) {
    			System.out.println( f.getName() );//获取属性名
    			System.out.println( f.getType().getName() );//获取类型
    		}
    	}
    
    创建对象
    	@Test//创建对象
    	public void objectTest() throws Exception {
    		//1,创建Class对象
    		Class<?> clazz = Student.class;
    		
    		//2,创建对象
    		Object object = clazz.newInstance();//用无参构造
    		System.out.println(object);
    		
    		//指定要用哪个含参构造   --   参数是字节码对象的类型
    		Constructor<?> c = clazz.getConstructor(String.class,int.class);
    		Object object2 = c.newInstance("jack",20);//用含参构造
    		System.out.println(object2);//Student [name=jack, age=20]
    	}
    

    暴力反射–就是反射类的私有数据:
    获取私有属性
    	@Test   //反射私有属性
    	public void fieldTest() throws Exception {
    		//1,创建Class对象
    		Class<?> clazz = Person.class;
    		
    		//2,反射 一个  私有属性
    		Field field = clazz.getDeclaredField("name");
    		System.out.println(field.getType().getName());//获取属性的类型
    		
    		//设置私有属性的值
    		Object obj = clazz.newInstance();
    		field.setAccessible(true);//设置私有可见!!java.lang.IllegalAccessException: 
    		//set(m,n)-m是你要给哪个对象设置值,n是要给对象的指定属性设置什么值
    		field.set(obj, "肉丝");
    		
    		System.out.println(field.get(obj));//查看值
    		
    		//3、反射  所有  私有属性
    		Field[] fs = clazz.getDeclaredFields();
    		for (Field f : fs) {
    			System.out.println(f.getType().getName());//属性的类型
    			System.out.println(f.getName());//属性的名字
    			
    			f.setAccessible(true);//设置私有可见
    			Object o = clazz.newInstance();
    			System.out.println( f.get(o) +"===");//获取属性值
    		}
    	}
    
    获取私有方法
    	@Test
    	public void methodTest() throws Exception {
    		//1,创建Class对象
    		Class<?> clazz = Person.class;
    		
    		//2,获取  一个  私有方法
    		Method method = clazz.getDeclaredMethod("test", null);
    		Class<?>[] ps = method.getParameterTypes();
    		System.out.println(  Arrays.toString(ps) );
    	
    		//3,执行方法
    		//invoke(m,n)--m是要执行哪个对象的方法 n是方法需要的参数
    		Object obj = clazz.newInstance();
    		method.setAccessible(true);//设置私有可见
    		method.invoke(obj, null);
    		
    		//4,获取  所有  私有方法  --  2min
    		Method[] ms = clazz.getDeclaredMethods();
    		for (Method m : ms) {
    			Class<?>[] cs =m.getParameterTypes();
    			System.out.println(  Arrays.toString(cs) );
    			
    			//执行方法
    			Object o = clazz.newInstance();
    			m.setAccessible(true);//设置隐私可见
    			//?先获取到想要执行的方法
    //			m.invoke(o, null);必须要先指定要执行哪个方法
    		}
    	}
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值