通过反射获取类的结构信息(常用方法)
第一组:java.lang.Class类
- getName:获取全类名
- getSimpleName:获取简单类名
- getFields:获取所有public修饰的属性,包含本类以及父类的
- getDeclaredFields:获取本类中所有属性
- getMethods:获取所有public修饰的方法,包含本类以及父类的
- getDeclaredMethods:获取本类中所有方法
- getConstructors: 获取本类所有public修饰的构造器
- getDeclaredConstructors:获取本类中所有构造器
- getPackage:以Package形式返回包信息
- getSuperClass:以Class形式返回父类信息
- getInterfaces:以Class[形式返回接口信息
- getAnnotations:以Annotation[形式返回注解信息
第二组: java.lang.reflect.Field类
- getModifiers:以int形式返回修饰符[说明:默认修饰符是0,public是1, private是2,protected是4,static是8, final是16] 如果是组合的则相加 如public static … -> 1+8
- getType:以Class形式返回类型
- getName:返回属性名
第三组: java.lang.reflect.Method类
- getModifiers:以int形式返回修饰符[说明:默认修饰符是0,public是1,private是2,protected是4,static是8, final是16]
- getReturnType:以Class形式获取返回类型
- getName:返回方法名
- getParameterTypes:以Class返回参数类型数组
第四组: java.lang.reflect.Constructor类
- getModifiers: 以int形式返回修饰符
- getName:返回构造器名(全类名)
- getParameterTypes:以Class[返回参数类型数组
例:
package com.z.reflection;
import org.junit.jupiter.api.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.spec.RSAOtherPrimeInfo;
/**
* @author 小白
* @version 1.0
* 演示如何通过反射获取类的结构信息
*/
public class ReflectionUtils {
public static void main(String[] args) {
}
//第一组方法API
@Test
public void api_01() throws ClassNotFoundException {
//得到Class对象
Class<?> personCls = Class.forName("com.z.reflection.Person");
// getName:获取全类名
System.out.println(personCls.getName());
// getSimpleName:获取简单类名
System.out.println(personCls.getSimpleName());
// getFields:获取所有public修饰的属性,包含本类以及父类的
Field[] fields = personCls.getFields();
System.out.println("本类以及父类的属性:");
for (Field field : fields) {
System.out.println(field.getName());
}
// getDeclaredFields:获取本类中所有属性
Field[] declaredFields = personCls.getDeclaredFields();
System.out.println("本类所有属性:");
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
// getMethods:获取所有public修饰的方法,包含本类以及父类的
Method[] methods = personCls.getMethods();
System.out.println("本类以及父类的方法:");
for (Method method : methods) {
System.out.println(method);
}
// getDeclaredMethods:获取本类中所有方法
Method[] declaredMethods = personCls.getDeclaredMethods();
System.out.println("本类的方法:");
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
// getConstructors: 获取本类所有public修饰的构造器
Constructor<?>[] constructors = personCls.getConstructors();
System.out.println("本类public构造器:");
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName());
}
// getDeclaredConstructors:获取本类中所有构造器
Constructor<?>[] dc = personCls.getDeclaredConstructors();
System.out.println("本类所有的构造器:");
for (Constructor<?> constructor : dc) {
System.out.println(constructor.getName());
}
// getPackage:以Package形式返回包信息
System.out.println();
System.out.println(personCls.getPackage());
// getSuperClass:以Class形式返回父类信息
System.out.println();
Class<?> superclass = personCls.getSuperclass();
System.out.println(superclass);
// getInterfaces:以Class[形式返回接口信息
Class<?>[] interfaces = personCls.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println("接口信息:" + anInterface);
}
// getAnnotations:以Annotation[形式返回注解信息
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("注解信息:" + annotation);
}
}
@Test
public void api_02() throws ClassNotFoundException {
//第二组方法API
Class<?> personCls = Class.forName("com.z.reflection.Person");
Field[] declaredFields = personCls.getDeclaredFields();
System.out.println("本类中所有属性:");
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName()
+ " 该属性的修饰符值:" + declaredField.getModifiers()
+ " 该属性的类型:" + declaredField.getType());
}
//第三组方法API
Method[] declaredMethods = personCls.getDeclaredMethods();
System.out.println("本类以及父类的方法:");
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName()
+ " 该方法的访问修饰符值:" + declaredMethod.getModifiers()
+ " 该方法返回类型:" + declaredMethod.getReturnType());
//输出当前这个方法的形参数组情况
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
System.out.println("该方法的形参类型:");
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType);
}
}
//第四组......
}
}
class A{
public String hobby;
public A(){}
public void hi(){}
}
interface IA{
}
interface IB{
}
@Deprecated
class Person extends A implements IA, IB{
public String name;
protected int age;
String job;
private double sal;
public Person(){}
public Person(String name) {
this.name = name;
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
public void m1(String name, int age, double sal){
}
protected String m2(){
return null;
}
void m3(){
}
private void m4(){
}
}
通过反射创建对象
- 方式一:调用类中的public修饰的无参构造器工
- 方式二:调用类中的指定构造器
- Class类相关方法
i. newlnstance:调用类中的无参构造器,获取对应类的对象
ii. getConstructor(Class…clazz):根据参数列表,获取对应的public构造器对象
iii. getDecalaredConstructor(Class…clazz):根据参数列表,获取对应的所有构造器对 象 - Constructor类相关方法
i. setAccessible:暴破(可以使用反射访问private构造器)
ii. newInstance(Object…obj):调用构造器
例:
package com.z.reflection;
import java.lang.reflect.Constructor;
/**
* @author 小白
* @version 1.0
* 演示通过反射机制创建实例
*/
public class ReflectCreateInstance {
public static void main(String[] args) throws Exception {
Class<?> userClass = Class.forName("com.z.reflection.User");
//通过public的无参构造器创建实例
Object o = userClass.getConstructor().newInstance();
System.out.println(o);
//通过public的有参构造器创建实例
Constructor<?> constructor = userClass.getConstructor(String.class);
Object k = constructor.newInstance("k");
System.out.println(o);
//通过非public的有参构造器创建实例
Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
constructor1.setAccessible(true);//爆破,可以使用反射访问private构造器
Object q = constructor1.newInstance(12, "q");
System.out.println(q);
}
}
class User{
private int age = 18;
private String name = "z";
public User() {}
public User(String name){
this.name = name;
}
private User(int age, String name){
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
输出
User{age=18, name='z'}
User{age=18, name='z'}
User{age=12, name='q'}
通过反射访问类中的成员
- 根据属性名获取Field对象
Field f = clazz对象.getDeclaredField(属性名);
- 暴破:
f.setAccessible(true);//f是Field
- 访问
f.set(o,值); syso(f.get(o));
- 注意:如果是静态属性,则set和get中的参数o,可以写成null
例:
package com.z.reflection;
import java.lang.reflect.Field;
/**
* @author 小白
* @version 1.0
* 演示反射操作属性
*/
public class ReflectAccessProperty {
public static void main(String[] args) throws Exception {
//得到Student对象对应的Class对象
Class<?> stuClass = Class.forName("com.z.reflection.Student");
//创建对象
Object o = stuClass.getConstructor().newInstance();
System.out.println(o.getClass());
//使用反射得到属性对象
Field age = stuClass.getField("age");
age.set(o, 16);//通过反射来操作属性
System.out.println(o);
System.out.println(age.get(o));//返回age属性的值
//静态属性
Field name = stuClass.getDeclaredField("name");
name.setAccessible(true);//爆破
// name.set(o,"k"); //也可
name.set(null, "k");
System.out.println(o);
//System.out.println(name.get(o));//也可
System.out.println(name.get(null));//获取属性值 要求name为static
}
}
class Student {
public int age;
private static String name;
public Student(){}
@Override
public String toString() {
return "Student{" +
"age=" + age +
"name=" + name +
'}';
}
}
输出:
class com.z.reflection.Student
Student{age=16name=null}
16
Student{age=16name=k}
k
-
根据方法名和参数列表获取Method方法对象:
Method m = clazz.getDeclaredMethod(防方法名,XX.class);
-
获取对象:Object o=clazz.newInstance0;
-
暴破:m.setAccessible(true);
-
访问:Object returnValue = m.invoke(o,实参列表);
-
注意:如果是静态方法,则invoke的参数o,可以写成null!
例:
package com.z.reflection;
import java.lang.reflect.Method;
/**
* @author 小白
* @version 1.0
* 演示通过反射调用方法
*/
public class ReflectAccessMethod {
public static void main(String[] args) throws Exception {
//得到Boss类对应的Class对象
Class<?> bossCls = Class.forName("com.z.reflection.Boss");
//创建对象
Object o = bossCls.getConstructor().newInstance();
//调用public的hi方法
//Method hi = bossCls.getMethod("hi", String.class);//OK
Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK
//调用
hi.invoke(o, "kk");
//调用private static 方法
Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
say.setAccessible(true);
System.out.println(say.invoke(o, 10, "张三", '男'));
//因为say方法是static的,还可以这样调用
System.out.println(say.invoke(null, 12, "李四", '男'));
//在反射中,如果方法有返回值,统一返回Object,但他的运行类型的方法定义的返回类型一致
Object reVal = say.invoke(null, 20, "王五", '男');
System.out.println("reVal 的运行类型 : " + reVal.getClass());
}
}
class Boss{
public int age;
private static String name;
public Boss() {}
private static String say(int n, String s, char c){
return n + " " + s + " " + c;
}
public void hi(String s){
System.out.println("hi " + s);
}
}
输出:
hi kk
10 张三 男
12 李四 男
reVal 的运行类型 : class java.lang.String