Java反射

我与影子孤独终老i 提交于 2019-12-25 06:50:33

反射

反射相关API
  • java.lang.Class:类
  • java.lang.reflect.Method:方法
  • java.lang.reflect.Field:成员变量
  • java.lang.reflect.Constructor:构造方法

首先创建Person类用来测试反射

public class Person extends Animal implements Move, Study {

    private String msg;
    
    public int age;
    
    public Person(){
        System.out.println("这是一个公共无参构造方法");
    }    
    
    public Person(String msg){
        this.msg = msg;
        System.out.println("这是一个公共带参构造方法");
    }
    
    private Person(String msg, int age){
        this.msg = msg;
        this.age = age;
        System.out.println("这是一个私有带参构造方法");
    }    
    
    public void showMsg(){
        System.out.println("这是一个公共无参方法");
    }    
    
    public void showMy(String str, int i){
        System.out.println("这是一个公共有参方法");
    }
    
    private void show(String str){
        System.out.println("这是一个私有有参方法");
    }
    
    @Override
    public void toMove() {
        System.out.println("Move接口的toMove方法");
    }
    @Override
    public void studyMath() {
        System.out.println("Study接口的studyMath方法");
    }
    
}

Animal.java

public class Animal {
    public void run(){
        System.out.println("这是Animal类的run方法");
    }
}

Study.java

public interface Study {
    void studyMath();
}

Move.java

public interface Move {
    void toMove();
}
Class 类
  • 对于每一个类而言JRE都为其保留了一个不变的Class类型的对象,一个Class对象包含了指定莫各类的所有有关信息。
  • Class本身也是一个类
  • Class对象只能由系统建立对象
  • 一个类在JVM中只能有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的.class文件
  • 每个类的实例优惠记得自己是由哪个Class实例生成的
  • 通过Class可以完整的得到一个类中的完整结构

使用getClass方法获取类

Person p = new Person();
//使用getClass获取到的对象中包含了Person累的所有信息
System.out.println(p.getClass());

运行结果
在这里插入图片描述

Class类中的常用方法

方法名 描述
forName(String name) 根据类的全类名(包名+类名)获取Class对象
newInstance() 创建目标类对象
getName() 获取全类名
getSuperclass() 获取父类的Class对象
getInterfoces() 获取所有实现的接口
getClassLoader() 获取类的类加载器
getConstructors() 获取所有构造器
getDeclaredFields() 获取所有的属性
getMethods() 获取对应的方法
实例化Class类对象

已知具体的类,通过类的class属性获取,该方法最安全可靠,程序性能最高

Class c = Person.class;

已知某个类的实例,调用该实例的getClass方法获取

Class c = person.getClass();

已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName获取,可能抛出ClassNotFoundException

Class c = Class.forName("com.java.test.reflect.Person");

使用类加载器获取,需知类的全类名

ClassLoader cl = this.getClass().getClassLoader();
Class c = cl.loadClass("com.java.test.reflect.Person");
获取指定类的父类

示例代码

try {
    Class c = Class.forName("com.java.test.reflect.Person");
    Class sc = c.getSuperclass();
    System.out.println(sc.getName());
} catch (Exception e) {
    e.printStackTrace();
}

运行结果
在这里插入图片描述

获取指定类的接口类

示例代码

Class c = Class.forName("com.java.test.reflect.Person");
Class[] cs = c.getInterfaces();
for (Class clazz : cs){
    System.out.println(clazz.getName());
}

运行结果
在这里插入图片描述

获取指定类的构造方法

获取公共构造方法

Class c = Class.forName("com.java.test.reflect.Person");
Constructor[] constructors = c.getConstructors();
for (Constructor constructor:constructors){    
    //获取方法名
    System.out.println(constructor.getName());    
    //获取权限修饰符,1为public,2为private
    System.out.println(constructor.getModifiers());    
    //获取参数的Class    
    Class[] parameterTypes = constructor.getParameterTypes();
    for (Class clazz :parameterTypes){
        System.out.println(clazz.getName());    
    }
    System.out.println("-----------------");
}

运行结果
在这里插入图片描述

获取所有构造方法

Constructor[] constructors = c.getDeclaredConstructors();

运行结果
在这里插入图片描述

使用反射创建对象

使用class创建

Object obj = c.newInstance();
  • 此方法在jdk9中被弃用
  • 使用以下方法代替

无参构造方法调用

Class c = Class.forName("com.java.test.reflect.Person");
Person p = (Person) c.getConstructor().newInstance();
p.run();

运行结果
在这里插入图片描述

有参构造方法调用

Class c = Class.forName("com.java.test.reflect.Person");
Person p = (Person) 
c.getConstructor(String.class).newInstance("test");
p.run();

运行结果
在这里插入图片描述

破除封装调用私有构造方法

Class c = Class.forName("com.java.test.reflect.Person");
Constructor constructor = c.getDeclaredConstructor(String.class, int.class);
//解除封装
constructor.setAccessible(true);
Person p = (Person) constructor.newInstance("test", 11);
p.run();

运行结果
在这里插入图片描述

反射获取类的方法

获取公有方法

public Method[] getMethods()

获取所有方法

public Method[] getDeclaredMethods()

Method类的方法

//取得返回值
public Class<?> getReturnType()
//取得所有参数
public Class<?>[] getParameterTypes()
//取得修饰符
public int getModifiers

示例代码

Class c = Class.forName("com.java.test.reflect.Person");
Method[] methods = c.getDeclaredMethods();
for (Method m : methods){
    System.out.println("方法名:"+m.getName());
    System.out.println("修饰符:"+m.getModifiers());
    System.out.println("返回类型:"+m.getReturnType());
    Class[] paraClass = m.getParameterTypes();
    for (Class pc : paraClass){
        System.out.println("参数类型:"+pc.getName());
    }
    System.out.println("-------------------");
}

运行结果

方法名:showMsg
修饰符:1
返回类型:void
-------------------
方法名:showMy
修饰符:1
返回类型:void
参数类型:java.lang.String
参数类型:int
-------------------
方法名:studyMath
修饰符:1
返回类型:void
-------------------
方法名:show
修饰符:2
返回类型:void
参数类型:java.lang.String
-------------------
方法名:toMove
修饰符:1
返回类型:void
-------------------
通过反射获取类的属性和包

获取公共Field

public Field[] getFields();

获取所有Field

public Field[] getDeclaredFields();

Field类的方法

//以整数形式返回Field的修饰符
public int getModifiers();
//得到Field的属性类型
public Class<?> getType();
//返回Field的名称
public String getName();

示例代码

Class c = Class.forName("com.java.test.reflect.Person");
Field[] fields = c.getDeclaredFields();
for (Field f : fields){
    System.out.println(f.getName());
    System.out.println(f.getModifiers());
    System.out.println(f.getType().getName());
    System.out.println("-----------------");
}

运行结果

msg
2
java.lang.String
-----------------
age
1
int
-----------------
反射调用指定方法

调用方法示例

Class c = Class.forName("com.java.test.reflect.Person");
//获取构造方法
Constructor constructor = c.getConstructor();
//使用构造方法创建对象
Object obj = constructor.newInstance();
/**
 * 获取指定方法
 * string:方法名
 * 参数类型
 */
Method method = c.getMethod("showMy", String.class, int.class);
/**
 * 运行方法
 * obj:创建的指定类的对象
 * 传入方法的参数
 */
method.invoke(obj, "test", 1);

运行结果

这是一个公共无参构造方法
这是一个公共有参方法

Process finished with exit code 0

调用私有方法

method.setAccessible(true);//解除私有封装
反射获取修改类的属性

示例代码

Class c = Class.forName("com.java.test.reflect.Person");
Constructor constructor = c.getConstructor();
Object obj = constructor.newInstance();
Field field = c.getField("age");
field.set(obj, 10);
System.out.println(field.get(obj));

运行结果

这是一个公共无参构造方法
10

Process finished with exit code 0

调用私有属性

field.setAccessible(true);//解除私有封装
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!