1、定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。
2、反射相关类
类名 |
用途 |
Class类 |
代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 |
代表类的成员变量(成员变量也称为类的属性) |
Method类 |
代表类的方法 |
Constructor类 |
代表类的构造方法 |
2.1、Class类
Class类代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
2.1.1 、获得类相关的方法
方法 |
作用 |
asSubclass(Class<U> clazz) |
把传递的类的对象转换成代表其子类的对象 |
Cast |
把对象转换成代表类或是接口的对象 |
getClassLoader() |
获得类的加载器 |
getClasses() |
返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
getDeclaredClasses() |
返回一个数组,数组中包含该类中所有类和接口类的对象 |
forName(String className) |
根据类名返回类的对象 |
getName() |
获得类的完整路径名字 |
newInstance() |
创建类的实例 |
getPackage() |
获得类的包 |
getSimpleName() |
获得类的名字 |
getSuperclass() |
获得当前类继承的父类的名字 |
getInterfaces() |
获得当前类实现的类或是接口 |
2.1.2 、获得类中属性相关的方法
方法 |
作用 |
getField(String name) |
获得某个公有的属性对象 |
getFields() |
获得所有公有的属性对象 |
getDeclaredField(String name) |
获得某个属性对象 |
getDeclaredFields() |
获得所有属性对象 |
2.1.3 、获得类中注解相关的方法
方法 |
作用 |
getAnnotation(Class<A> annotationClass) |
返回该类中与参数类型匹配的公有注解对象 |
getAnnotations() |
返回该类所有的公有注解对象 |
getDeclaredAnnotation(Class<A> annotationClass) |
返回该类中与参数类型匹配的所有注解对象 |
getDeclaredAnnotations() |
返回该类所有的注解对象 |
2.1.4 、获得类中构造器相关的方法
方法 |
作用 |
getConstructor(Class...<?> parameterTypes) |
获得该类中与参数类型匹配的公有构造方法 |
getConstructors() |
获得该类的所有公有构造方法 |
getDeclaredConstructor(Class...<?> parameterTypes) |
获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() |
获得该类所有构造方法 |
2.1.5 、获得类中方法相关的方法
方法 |
作用 |
getMethod(String name, Class...<?> parameterTypes) |
获得该类某个公有的方法 |
getMethods() |
获得该类所有公有的方法 |
getDeclaredMethod(String name, Class...<?> parameterTypes) |
获得该类某个方法 |
getDeclaredMethods() |
获得该类所有方法 |
2.1.6 、类中其他重要的方法
方法 |
作用 |
isAnnotation() |
如果是注解类型则返回true |
isAnnotationPresent(Class<? extends Annotation> annotationClass) |
如果是指定类型注解类型则返回true |
isAnonymousClass() |
如果是匿名类则返回true |
isArray() |
如果是一个数组类则返回true |
isEnum() |
如果是枚举类则返回true |
isInstance(Object obj) |
如果obj是该类的实例则返回true |
isInterface() |
如果是接口类则返回true |
isLocalClass() |
如果是局部类则返回true |
isMemberClass() |
如果是内部类则返回true |
2.2、Field类
Field代表类的成员变量(成员变量也称为类的属性)。
方法 |
作用 |
equals(Object obj) |
属性与obj相等则返回true |
get(Object obj) |
获得obj中对应的属性值 |
set(Object obj, Object value) |
设置obj中对应属性值 |
2.3、Method类
Method代表类的方法。
方法 |
作用 |
invoke(Object obj, Object... args) |
传递object对象及参数调用该对象对应的方法 |
2.4、Constructor类
Constructor代表类的构造方法。
方法 |
作用 |
newInstance(Object... initargs) |
根据传递的参数创建类的对象 |
3、示例
首先构造一个实体类Person.java,然后通过反射方法示例创建对象、反射私有构造方法、反射私有属性、反射私有方法。
3.1、Person.java
package com.zjf.reflect;
public class Person {
private final static String TAG = "Person";
private String name;
private int age;
public Person() {}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
private String privateMethod(int index) {
String string = null;
switch (index) {
case 0:
string = "param is 0";
break;
case 1:
string = "param is 1";
break;
default:
string = "param is 0";
}
return string;
}
}
3.2、反射方法
带有Declared修饰的方法可以反射到私有的方法,没有Declared修饰的只能用来反射公有的方法。
package com.zjf.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectUtils {
//通过反射创建对象
public static void reflectNewInstance() {
try {
Class<?> personClass = Class.forName("com.zjf.reflect.Person");
Object personObject = personClass.newInstance();//Person类中必须写空参的构造方法
Person person = (Person) personObject;
person.setName("张俊峰");
person.setAge(25);
System.out.println("reflectNewInstance person == " + person.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//反射私有的构造方法
public static void reflectPrivateConstructor() {
try {
Class<?> personClass = Class.forName("com.zjf.reflect.Person");
//getDeclaredConstructor参数与构造方法的参数有关
Constructor<?> personConstructor = personClass.getDeclaredConstructor(String.class,int.class);
//暴力反射
personConstructor.setAccessible(true);
Person person = (Person)personConstructor.newInstance("朱伟",27);
System.out.println("reflectPrivateConstructor person == " + person.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//反射私有成员变量
public static void reflectPrivateField() {
try {
Class<?> personClass = Class.forName("com.zjf.reflect.Person");
Person person = (Person)personClass.newInstance();
person.setName("张小奔");
person.setAge(25);
Field tagField = personClass.getDeclaredField("TAG");//变量名
Field nameField = personClass.getDeclaredField("name");
tagField.setAccessible(true);
nameField.setAccessible(true);
System.out.println("reflectPrivateField tagField == " + (String)tagField.get(person));
System.out.println("reflectPrivateField nameField == " + (String)nameField.get(person));
nameField.set(person, "zjf");
System.out.println("reflectPrivateField person == " + person.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//反射私有方法
public static void reflectPrivateMethod() {
try {
Class<?> personClass = Class.forName("com.zjf.reflect.Person");
Person person = (Person)personClass.newInstance();
Method privateMethod = personClass.getDeclaredMethod("privateMethod", int.class);
privateMethod.setAccessible(true);
System.out.println("reflectPrivateMethod return == " + privateMethod.invoke(person, 0));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4、总结
image.png