在说反射之前,必须得先说说java的类加载器,类加载器的定义:将.class文件加载到内在中,并为之生成对应的Class对象。
一般有三种
1 Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
2 Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
3 Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
接下来,我们在说反射
反射的定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。【简单来说 通过class字节码文件来获取他的构造方法,方法和属性的这种技术,叫做反射】
反射的几种用法
在使用反射之前,我们需要获取Class对象
一般有三种方式可以获得
1类名.class
2.对象.getClass()
3.使用Class.forName("类的完整包名"); 推荐使用这种。
通过反射,我们可以获取到类的构造方法,成员变量,成员方法。(包含private的)所以一般为了安全,字节码文件会加密的。
获取构造方法
获取构造方法
getConstructors //返回构造方法数组
getDeclaredConstructors //获取私有的构造方法数组
创建对象
newInstance()
con.newInstance(“zhangsan", 20); //有参构造
获取成员变量
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
修改成员的值
set(Object obj,Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
获取成员方法
获取所有方法
getMethods
getDeclaredMethods
获取单个方法
getMethod
getDeclaredMethod
暴力访问
method.setAccessible(true); //可以访问私有的
以下是代码
普通java类
package com.demo; public class Demo { private String name; private int age; public String ssss; public Demo(String name) { this.name = name; } public Demo() { } private Demo(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show() { System.out.println(name); } public void showString(String s) { System.out.println("s____" + s); } public String gets(String s) { return s; } @Override public String toString() { return ("name__" + name + "age__" + age); } }
测试构造方法【目的是为了实例化对象】
@Test public void testConstructor() { Class<?> dc; try { dc = Class.forName("com.demo.Demo"); Constructor[] cons = dc.getConstructors(); for(Constructor cc:cons) { System.out.println(cc); //结果如下 //public com.demo.Demo() //public com.demo.Demo(java.lang.String) } //获取单个 Constructor cc = dc.getConstructor(String.class); Object ob = cc.newInstance("aaaa"); System.out.println(ob); //获取私有的构造该方法 Constructor ccint = dc.getDeclaredConstructor(int.class); ccint.setAccessible(true);//暴力访问 Object o = ccint.newInstance(111); System.out.println(o); //结果 age__111 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
测试成员变量以及成员方法
@Test public void testFieldAndMethod() { Class<?> dc; try { dc = Class.forName("com.demo.Demo"); Field[] fields = dc.getDeclaredFields(); //获取所有的成员变量 包含私有的 for (Field f : fields) { System.out.println(f.toString()); } // 结果如下 // private java.lang.String com.demo.Demo.name // private int com.demo.Demo.age // public java.lang.String com.demo.Demo.ssss Field nameField = dc.getDeclaredField("name"); // 暴力访问 nameField.setAccessible(true); Constructor cc = dc.getConstructor(String.class); Object ob = cc.newInstance("string"); //赋值语句 nameField.set(ob, "name test "); System.out.println(ob); //结果 name__name test //3成员方法 Method showStringMethod = dc.getDeclaredMethod("showString", String.class); showStringMethod.invoke(ob, "ssss"); //通过invok执行 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }