java中的反射
-
反射是什么?
JAVA反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法。对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
想要解剖一个类,必须先要获得该类的字节码对象。
-
三种方式获得字节码对象
(1.创建对象阶段)Object类的getClass()方法
示例:Person p = new Person();
Class clazz = p.getClass()
(2.源文件阶段)Class类的静态方法
示例:class.forName("类名")
Class clazz = class.forName("com.pr.Person")
(3.字节码阶段)Class clazz = Person.class
-
字节码对象的newInstance()方法通过无参构造函数创建对象
public class Demo { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.pr2.Person"); // 获取字节码对象 Person p = (Person) clazz.newInstance(); // 通过无参构造方法创建对象 p.eat(); } } class Person{ public Person() {}; public void eat(){ System.out.println("吃饭"); } }
-
字节码对象通过有参构造函数创建对象
public class demo { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.pr3.Person"); Constructor c = clazz.getConstructor(String.class,int.class); // 发射阶段,都是操作字节码对象的 Person p = (Person) c.newInstance("张三",13); System.out.println(p); } } class Person{ private String name; private int age; // public Person() {} 无参构造注释掉 public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
-
字节码对象获取、修改私有成员变量
public class Demo { public static void main(String[] args) throws Exception { Person p = new Person("张三",13); System.out.println(p); Class clazz = p.getClass(); Field f = clazz.getDeclaredField("name"); // 暴力反射获取字段 f.setAccessible(true); // 去除私有权限 f.set(p,"李四"); System.out.println(p); } } class Person{ private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
-
字节码对象获取无参方法并使用
public class Demo { public static void main(String[] args) throws Exception { My m = new My(); Class clazz = m.getClass(); Method method = clazz.getMethod("eat"); method.invoke(m); } } class My{ public void eat(){ System.out.println("我今天吃了一顿KFC"); } }
-
字节码对象获取有参方法并使用
public class Demo { public static void main(String[] args) throws Exception { My m = new My(); Class clazz = m.getClass(); Method method = clazz.getMethod("eat",int.class); method.invoke(m,3); } } class My{ public void eat(int num){ System.out.println("我今天吃了" + num + "顿KFC"); } }
-
利用上面的例子(字节码对象获取有参方法并使用)可以实现用反射越过泛型检查
public class Demo { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { ArrayList<Integer> list = new ArrayList<>(); list.add(100); list.add(200); Class clazz = Class.forName("java.util.ArrayList"); Method m = clazz.getMethod("add", Object.class); m.invoke(list,"哈哈哈"); System.out.println(list); } }
代码成就万世基积沙镇海,梦想永在凌云意意气风发。