一、什么是反射?
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类的所有方法和属性;对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
二、反射获取类的三种方式
反射其实是获取类的字节码文件,也就是JVM可以识别加载.class文件。
通过Class<?>获取类信息。
1. 通过className.class获取
package test;
public class ClassTest {
public static void main(String[] args) {
Class<?> clazz = User.class;
System.out.println(clazz.getName()); //test.User
} //name就是他的路径名(包名.类名)
}
class User {
int i = 0;
}
2. 通过Object.getClass()获取
package test;
public class ClassTest {
public static void main(String[] args) {
User user = new User();
Class<?> clazz = user.getClass();
System.out.println(clazz.getName()); //test.User
} //name就是他的路径名(包名.类名)
}
class User {
int i = 0;
}
3. 通过Class.forName(“类的路径”)获取
package test;
public class ClassTest { //需要抛出异常,根据路径可能会找不到这个类
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz = Class.forName("test.User");
System.out.println(clazz.getName()); //test.User
} //name就是他的路径名(包名.类名)
}
class User {
int i = 0;
}
第一种需要导入类的包,依赖性太强。
第二种已经创建了对象,那么这个时候就不需要进行反射了。
所以我们一般选中第三种方式,架构一般用这种方式。
三、通过反射获取类的属性、方法以及构造方法
1. 获取类的属性
package test;
import java.lang.reflect.Field;
public class ClassTest {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("test.User");
System.out.println("*******获取所有公共字段******");
Field i = clazz.getField("i"); //获取类的公共字段的特定属性
Field[] fields = clazz.getFields(); //获取类的公共字段的所有属性
System.out.println("*******获取所有声明字段******");
Field field = clazz.getDeclaredField("i"); //获取类的声明字段的特定属性
Field[] declaredFields = clazz.getDeclaredFields();//获取类的声明字段的所有属性
System.out.println("*******获取私有属性并使用******");
Object object = clazz.getConstructor().newInstance();
field.setAccessible(true); //假如不是私有属性则没有这一行
field.set(object,2);
User user = (User) object;
System.out.println(user.i);
}
}
class User {
private int i = 0;
}
2. 获取类的方法
package test;
import java.lang.reflect.Method;
public class ClassTest {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("test.User");
System.out.println("*******获取公共方法******");
Method publicMethod = clazz.getMethod("publicMethod"); //获取类的公共方法的特定方法
Method[] methods = clazz.getMethods(); //获取类的公共方法的所有方法
System.out.println("*******获取声明方法******");
Method declaredMethod = clazz.getDeclaredMethod("privateMethod"); //获取类的声明方法的特定方法
Method[] declaredMethods = clazz.getDeclaredMethods(); //获取类的声明方法的所有方法
System.out.println("*******获取私有方法并使用******");
Object object = clazz.getConstructor().newInstance();
declaredMethod.setAccessible(true); //将方法设为可访问
Object invoke = declaredMethod.invoke(object); //通过invoke()调用方法
}
}
class User {
public void publicMethod(){
System.out.println("测试public方法");
}
private void privateMethod(){
System.out.println("测试private方法");
}
}
3. 获取类的构造方法
package test;
import java.lang.reflect.Constructor;
public class ClassTest {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("test.User");
System.out.println("*******获取公共的无参构造方法******");
Constructor<?> constructor = clazz.getConstructor(null);
Constructor<?>[] constructors = clazz.getConstructors();
System.out.println("*******获取声明的无参构造方法******");
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(null);
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
System.out.println("*******构造方法的使用******");
Object object = clazz.getConstructor().newInstance();
}
}
class User {
int i = 0;
public User() {
}
}
四、反射的方法源码
1. 获取类的属性
@CallerSensitive
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
}
return field;
}
@CallerSensitive
public Field[] getFields() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyFields(privateGetPublicFields(null));
}
@CallerSensitive
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
}
return field;
}
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyFields(privateGetDeclaredFields(false));
}
2. 获取类的方法
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Method method = getMethod0(name, parameterTypes, true);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
}
@CallerSensitive
public Method[] getMethods() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyMethods(privateGetPublicMethods());
}
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
}
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyMethods(privateGetDeclaredMethods(false));
}
3. 获取类的构造方法
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return getConstructor0(parameterTypes, Member.PUBLIC);
}
@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyConstructors(privateGetDeclaredConstructors(true));
}
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return getConstructor0(parameterTypes, Member.DECLARED);
}
@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyConstructors(privateGetDeclaredConstructors(false));
}