参考文档:https://www.jianshu.com/p/9be58ee20dee;https://www.jianshu.com/p/1fc45c89e76b
反射用途:在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。运行期间我们不知道类对象,并无法通过new关键字去创建对象,这是我们可以利用反射的机制去创建对象,并获取构造方法,变量,方法,包名类名之类的。
获取类对象的三种方法:
-
使用 Class.forName 静态方法。当知道某类的全路径名时,可以使用此方法获取 Class 类对象。用的最多,但可能抛出 ClassNotFoundException 异常。
Class c1 = Class.forName(“java.lang.String”);
-
直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高。这说明任何一个类都有一个隐含的静态成员变量 class。这种方法只适合在编译前就知道操作的 Class。
Class c2 = String.class;
-
通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object类型的对象,而我不知道你具体是什么类,用这种方法。
获取类相关属性的方法:
包名类名信息:包名 c1.getPackage().getName()
完整类名 c1.getName()
类名,不含包名 c1.getSimpleName()
成员变量定义信息:getFields() 获得所有可见的成员变量,包括继承的变量
getDeclaredFields() 获得本类定义的成员变量,包括私有 不包括继承的变量
getField(变量名) getDeclaredField(变量名)
构造方法信息:getConstructors() 获得所有可见的构造方法
getDeclaredConstructors() 获得本类定义的构造方法,包括私有
getConstructor(参数类型列表) getDeclaredConstructor(int.class, String.class)
方法定义信息:getMethods() 获得所有可见的方法,包括继承的方法
getDeclaredMethods() 获得本类定义的方法,包括私有 不包括继承的方法
getMethod(方法名,参数类型列表) getDeclaredMethod(方法名, int.class, String.class)
创建实例:
执行无参构造创建实例:Object obj = c.newInstance();
执行有参构造创建实例:Constructor t = c.getConstructor(int.class, String.class);
Object obj = t.newInstance(6, "abc");
反射调用成员变量:
获取变量 Field f = c.getDeclaredField(变量名);
使私有成员允许访问 f.setAccessible(true);
反射给变量赋值 为指定实例的变量赋值,静态变量 f.set(实例, 值);
反射访问变量的值 访问指定实例的变量的值,静态变量, Object v = f.get(实例);
反射调用成员方法:
获取方法 Method m = c.getDeclaredMethod(方法名, 参数类型列表);
使私有方法允许被调用 m.setAccessible(true)
反射调用方法 让指定的实例来执行该方法 Object returnValue = m.invoke(实例, 参数数据)
package testone;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.Scanner;
public class ReflectTest2 {
public static void main(String[] args) throws Exception {
System.out.println("请输入类名");
String s = new Scanner(System.in).nextLine();
Class<?> s1 = Class.forName(s);
System.out.println(s1.getPackage().getName()); //包名
System.out.println(s1.getName()); //类名
System.out.println(s1.getSimpleName()); //简单类名
System.out.println("输出成员变量");
outputFields(s1);
System.out.println("输出构造方法");
outputContructs(s1);
System.out.println("输出常用方法");
outputMethods(s1);
}
private static void outputMethods(Class<?> s1) {
Method[] methods = s1.getDeclaredMethods();
for (Method method : methods) {
String methodName = method.getName();
Parameter[] parameters = method.getParameters();
System.out.println("常用方法:"+methodName+"的参数有:"+Arrays.deepToString(parameters));
}
}
private static void outputContructs(Class<?> s1) {
Constructor<?>[] constru = s1.getDeclaredConstructors();
for (Constructor<?> constructor : constru) {
String construName = constructor.getName();
Parameter[] parameters = constructor.getParameters();
System.out.println(construName+"参数有:"+Arrays.toString(parameters));
}
}
private static void outputFields(Class<?> s1) {
Field[] fields = s1.getDeclaredFields();
for (Field field : fields) {
String fieldType = field.getType().getName();
String fieldName = field.getName();
System.out.println(fieldType+":"+fieldName);
}
}
}
/** 自己创建了三个类:ClassA,ClassB,ClassC */
package testone;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class<ClassA> classA = (Class<ClassA>)Class.forName("testone.ClassA");
Field[] fields = classA.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
ClassB classB = new ClassB();
Class<? extends ClassB> class1 = classB.getClass();
Constructor<?>[] constructors = class1.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName());
}
Class<?> class2 = ClassC.class;
Method[] methods = class2.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
}
}