一.反射
反射就是在剖析一个类,了解这个类的构造,创建这个类对应的对象。
Class | 代表字节码的类,代表类的类 |
Field | 代表属性的类 |
Method | 代表方法的类 |
Constructor | 代表构造方法的类 |
Annotation | 代表注解的类 |
Package | 代表包的类 |
二.Class类
2.1 获取Class对象:必须有意义
①通过类名.class的方式来获取对应类的字节码对象
1 import java.util.List; 2 3 public class ClassDemo { 4 @SuppressWarnings("rawtypes") 5 public static void main(String[] args) { 6 7 // 每一个Class对象对应了一个实际的类,因此要求每一个Class都必须有意义 8 // 如果允许随意创建Class对象,就会导致Class对象没有实际对应的类 9 // Class clz0 = new Class(); 10 11 // 通过类名.class的方式来获取一个字节码对象 12 // clz表示的就是String的字节码 13 Class<String> clz = String.class; 14 System.out.println(clz); 15 16 // clz2表示的就是List的字节码 17 Class<List> clz2 = List.class; 18 System.out.println(clz2); 19 20 // clz3表示的就是String[]的字节码 21 Class<String[]> clz3 = String[].class; 22 System.out.println(clz3); 23 24 } 25 }
②通过对象.getClass()方法来获取这个对象对应的实际类的字节码对象
1 public class ClassDemo { 2 @SuppressWarnings("unchecked") 3 public static void main(String[] args) { 4 Object str = "abc"; 5 Class<String> clz = (Class<String>) str.getClass(); 6 System.out.println(clz); 7 } 8 } 9 10 //输出:class java.lang.String
③通过Class.forName(类的全路径名)的方法来获取指定类的字节码对象
1 import java.util.List; 2 3 public class ClassDemo { 4 @SuppressWarnings("unchecked") 5 public static void main(String[] args) throws ClassNotFoundException { 6 Class<String> clz = (Class<String>) Class.forName("java.lang.String"); 7 System.out.println(clz); 8 9 Class<List> clz2 = (Class<List>) Class.forName("java.util.List"); 10 System.out.println(clz2); 11 } 12 } 13 14 //输出: 15 //class java.lang.String 16 //interface java.util.List
2.2创建由此类
对象表示的类的新实例
2.2.1 newInstance
字节码对象.newInstance();
用处之举例:
Cat和Dog都实现了Animal接口,利用向上造型,将字符串利用Properties进行更改,可实现任意创建Cat对象或者Dog对象。
1 public class TestClassDemo { 2 @SuppressWarnings("unchecked") 3 public static void main(String[] args) throws Exception { 4 5 // 表示获取了Animal类对应的字节码 6 //"cn.hdu.reflection.Cat"可以用Properties进去获取 7 Class<Animal> clz = (Class<Animal>) Class.forName("cn.hdu.reflection.Cat"); 8 9 // 要求类中必须有无参构造 10 Animal a = clz.newInstance(); //产生对象 11 System.out.println(a); 12 13 } 14 15 } 16 17 interface Animal { 18 } 19 20 class Dog implements Animal { 21 22 @Override 23 public String toString() { 24 return "Dog"; 25 } 26 27 } 28 29 class Cat implements Animal { 30 31 @Override 32 public String toString() { 33 return "Cat"; 34 } 35 36 }
2.2.2 通过构造方法创建新实例
//只能获取public构造方法 Constructor<?>[] getConstructors() Constructor<T> getConstructor(类<?>... parameterTypes) //不区分是否是public的构造方法 Constructor<?>[] getDeclaredConstructors() Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) //需要用 Constructor对象.setAccessible(true);进行设置
举例:
1 import java.lang.reflect.Constructor; 2 3 public class ClassGetConstructorDemo { 4 public static void main(String[] args) throws Exception { 5 6 // clz代表String类的字节码 7 Class<String> clz = String.class; 8 9 // String(String) 10 // 只能获取public修饰的构造方法 11 Constructor<String> constructorPublic = clz.getConstructor(String.class); 12 String str = constructorPublic.newInstance("abc"); 13 System.out.println(str); 14 15 // String(byte[], int, int) 16 Constructor<String> constructorParameters = clz.getConstructor(byte[].class, int.class, int.class); 17 String str2 = constructorParameters.newInstance(new byte[] { 97, 98, 99, 100 }, 1, 3); 18 System.out.println(str2); 19 20 // 获取指定的构造方法,不区分是否是public的 21 Constructor<String> constructorPrivate = clz.getDeclaredConstructor(char[].class, boolean.class); 22 // 暴力破解/暴力拆除 23 constructorPrivate.setAccessible(true); 24 String str3 = constructorPrivate.newInstance(new char[] { 'a', 'b', 'c' }, true); 25 System.out.println(str3); 26 } 27 28 }
在String源码中是默认的,非public
2.3 获取方法
//public
Method getMethod(String name, 类<?>... parameterTypes)
Method[] getMethods() //获取所有公有方法(包含了父类的方法也包含Object类)
//非public
Method getDeclaredMethod(String name, 类<?>... parameterTypes)
Method[] getDeclaredMethods() //获取所有的成员方法,包括私有的(不包括继承的)
//m.setAccessible(true);
//使用所指定的方法:Method的对象.invoke(Object obj, Object... args);
1 import java.lang.reflect.Constructor; 2 import java.lang.reflect.Method; 3 4 public class ClassGetMethodDemo { 5 6 public static void main(String[] args) throws Exception { 7 8 Class<String> clz = String.class; 9 10 // 表示String(String) 11 Constructor<String> c = clz.getConstructor(String.class); 12 String str = c.newInstance("abcdefg"); 13 14 // 获取charAt(int) 15 // 只能获取public修饰的方法 16 Method m = clz.getMethod("charAt", int.class); 17 // 执行方法对象 18 // 相当于char ch = str.charAt(3); 19 char ch = (char) m.invoke(str, 3); 20 System.out.println(ch); 21 22 // 获取指定的方法 23 Method m2 = clz.getDeclaredMethod("lastIndexOfSupplementary", int.class, int.class); 24 m2.setAccessible(true); 25 int i = (int) m2.invoke(str, 2, 3); 26 System.out.println(i); 27 } 28 29 }
2.4 获取属性
//public Field getField(String name) Field[] getFields() //非public Field getDeclaredField(String name) Field[] getDeclaredFields() //f.setAccessible(true); //Field类 获取:Object get(Object obj) 设置:void set(Object obj, Object value) void setChar(Object obj, char c) void setDouble(Object obj, double d) void setInt(Object obj, int i) ... ...
1 import java.lang.reflect.Constructor; 2 import java.lang.reflect.Field; 3 4 public class ClassGetFieldDemo { 5 public static void main(String[] args) throws Exception { 6 7 Class<String> clz = String.class; 8 9 // 表示String(String) 10 Constructor<String> c = clz.getConstructor(String.class); 11 String str = c.newInstance("abcdefg"); 12 13 // 获取类中指定的属性 14 Field f = clz.getDeclaredField("hash"); 15 f.setAccessible(true); 16 System.out.println(f.get(str)); 17 // 设置属性的值 18 f.set(str, 125); 19 // 获取属性的值 20 System.out.println(f.get(str)); 21 } 22 }
2.5 获取注解
<A extends Annotation>A getAnnotation(类<A> annotationClass) Annotation[] getAnnotations() <A extends Annotation>A getDeclaredAnnotation(类<A> annotationClass) Annotation[] getDeclaredAnnotations()
2.6 Class类其它常用方法
1 import java.lang.reflect.TypeVariable; 2 import java.util.ArrayList; 3 import java.util.List; 4 5 public class ClassDemo { 6 7 @SuppressWarnings("rawtypes") 8 public static void main(String[] args) { 9 10 Class<String> clz = String.class; 11 12 // 获取这个类实现的所有的接口 13 Class[] ins = clz.getInterfaces(); 14 for (Class c : ins) { 15 System.out.println(c); 16 } 17 18 // 获取父类 19 Class superc = clz.getSuperclass(); 20 System.out.println(superc); 21 22 // 获取类的全路径名 23 System.out.println(clz.getName()); 24 // 获取类的简称 25 System.out.println(clz.getSimpleName()); 26 27 // 获取所在的包 28 System.out.println(clz.getPackage()); 29 30 List<String> list = new ArrayList<>(); 31 Class lclz = list.getClass(); 32 TypeVariable[] ts = lclz.getTypeParameters(); 33 for (TypeVariable typeVariable : ts) { 34 System.out.println(typeVariable); 35 } 36 37 // 判断是否是一个枚举 38 System.out.println(clz.isAnnotation()); 39 // 判断是否是一个基本类型 40 System.out.println(clz.isPrimitive()); 41 42 // 判断参数是否是指定类型的实例的 43 Object str = "abc"; 44 System.out.println(clz.isInstance(str)); 45 System.out.println(str instanceof String); 46 47 // 判断两个类之间是否有继承关系 48 System.out.println(Object.class.isAssignableFrom(String.class)); 49 50 } 51 52 }