反射
一、Class类 字节码文件类
获取字节码对象的三种方式:
1、类名 变量 = new 类名();
Class c = 变量.getClass();
2、Class c = 类名.class;
3、Class c = Class.forName("全路径的类名加包名");
二、获取字节码文件
需要反射的类:
1 public class Student { 2 private String name; 3 public int age; 4 static { 5 System.out.println("Student类进内存了"); 6 } 7 8 public Student() { 9 super(); 10 } 11 public Student(String name,int age) { 12 System.out.println("公共有参构造"); 13 } 14 private Student(String name) { 15 System.out.println("私有有参构造"); 16 } 17 18 19 public void eat() { 20 System.out.println("公共无参方法"); 21 } 22 public void sleep(String name) { 23 System.out.println("公共有参方法"); 24 } 25 26 public void sleep(String name,int age) { 27 System.out.println("公共有参方法"); 28 } 29 private void get(int age) { 30 System.out.println("私有有参方法"); 31 } 32 @Override 33 public String toString() { 34 return "Student [name=" + name + ", age=" + age + "]"; 35 } 36 37 }
1、方法:
getConstructors():获取public 修饰的构造方法
getDeclaredConstructors():获取所有的构造方法
以上返回 Constructor[] 数组
getConstructor(Class<?>... parameterTypes):获取指定参数的public 修饰的构造方法
getDeclaredConstructor(Class<?>... parameterTypes):获取指定参数的 构造方法,包括私有
以上返回 Constructor 对象
2、通过构造方法创建对象
a(public):
1 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, 2 InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 3 // 获取字节码文件 4 Class c = Class.forName("com.oracle.demo02.Student"); 5 // 获取指定参数的构造方法,无参数的不用写参数 6 Constructor con = c.getDeclaredConstructor(String.class, int.class); 7 // 使用该构造方法创建对象 8 Object obj = con.newInstance("小明", 20); 9 Student student = null; 10 // 向下转型 11 if (obj instanceof Student && obj != null) { 12 student = (Student) obj; 13 } 14 System.out.println(student); 15 }
b(所有的):
1 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, 2 InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 3 // 获取字节码文件 4 Class c = Class.forName("com.oracle.demo02.Student"); 5 // 获取指定参数的构造方法 6 Constructor declaredConstructor = c.getDeclaredConstructor(String.class); 7 // 当反射私有的构造方法时需要暴力反射 8 declaredConstructor.setAccessible(true); 9 // 创建对象 10 Object obj = declaredConstructor.newInstance("小红"); 11 Student stu = null; 12 // 向下转型 13 if (obj instanceof Student && obj != null) { 14 stu = (Student)obj; 15 } 16 System.out.println(stu); 17 }
3、通过反射获取成员变量
方法:
getFields():获取所有用public 修饰的变量
getDeclaredFields():获取所有的 变量(包括私有)
以上放回 Field[] 数组:
getField(String name):获取指定的public 修饰的变量
getDeclaredField(String name):获取指定变量,包括私有
获取和赋值:
a(public):
1 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { 2 // 获取字节码文件对象 3 Class c = Class.forName("com.oracle.demo02.Student"); 4 // 获取构造方法 5 Constructor constructor = c.getConstructor(); 6 // 创建对象,赋值时使用 7 Object obj = constructor.newInstance(); 8 Student stu = null; 9 // 向下转型 10 if (obj instanceof Student && obj != null) { 11 stu = (Student)obj; 12 } 13 Field field = c.getField("age"); 14 // 设置值 15 field.set(stu, 20); 16 // 取值 17 System.out.println(field.get(stu)); 18 }
b(所有的):
1 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { 2 // 获取字节码文件对象 3 Class c = Class.forName("com.oracle.demo02.Student"); 4 // 获取构造方法 5 Constructor constructor = c.getConstructor(); 6 // 创建对象,赋值时使用 7 Object obj = constructor.newInstance(); 8 Student stu = null; 9 // 向下转型 10 if (obj instanceof Student && obj != null) { 11 stu = (Student)obj; 12 } 13 14 Field field = c.getDeclaredField("name"); 15 // 暴力反射,取消 field 属性对象 的Java 语言检查访问检查 16 field.setAccessible(true); 17 // 设置值 18 field.set(stu, "小红"); 19 // 取值 20 System.out.println(field.get(stu)); 21 }
4、通过反射调用方法:
方法:
getMethods():获取public 修饰的所有方法
getDeclaredMethods():获取所有方法,包括私有的
以上返回 Method[] 数组
getMethod(String name, Class<?>... parameterTypes):获取指定方法名和指定参数的方法 并 用 public 修饰的方法
getDeclaredMethod(String name, Class<?>... parameterTypes):获取 指定 方法名和指定参数 的 所有方法,包括私有
获取并调用:
a(public):
1 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { 2 // 获取字节码文件 3 Class c = Class.forName("com.oracle.demo02.Student"); 4 // 创建对象 5 Object obj = c.newInstance(); 6 // 获取指定方法,当没有参数是,第二个参数不写 7 Method method = c.getMethod("sleep", String.class); 8 // 执行 9 method.invoke(obj, "睡觉"); 10 }
b(所有的):
1 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { 2 // 获取字节码文件 3 Class c = Class.forName("com.oracle.demo02.Student"); 4 // 创建对象 5 Object obj = c.newInstance(); 6 // 获取指定方法 7 Method declaredMethod = c.getDeclaredMethod("get", int.class); 8 // 暴力反射 9 declaredMethod.setAccessible(true); 10 // 调用 11 declaredMethod.invoke(obj, 16); 12 }
5、泛型擦除:
1 public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 2 ArrayList<Integer> list = new ArrayList<Integer>(); 3 list.add(3); 4 list.add(5); 5 // 获取 ArrayList 的字节码文件 6 Class c = list.getClass(); 7 // 获取add方法 8 Method method = c.getMethod("add", Object.class); 9 // 传入的对象是需要被擦除的list集合,并执行 10 method.invoke(list, "小红"); 11 // 注意接收的使用用 Object 接收,如果需要操作,再向下转型成对应的类 12 Object str = list.get(2); 13 System.out.println(str); 14 }