JAVA-反射

282 阅读3分钟

常用类

可以查看api文档,都是在java.lang.reflect包下面

四大常用类

  1. Class类 获取需要加载的类
  2. Field类 获取该类的属性字段
  3. Method类 获取该类的方法
  4. Constructor类 获取该类的构造器

实例

public static void main(String[] args) throws Exception {
    //反射入门
    Properties properties = new Properties();
    properties.load(new FileInputStream("src\\re.properties"));

    //获取类名和需要使用的方法
    String classfull = properties.getProperty("classfull");
    String methodName = properties.getProperty("method");

    //加载对应的类对象 Class类对象 classfull
    Class<?> aClass = Class.forName(classfull);
    // 通过Class类对象获取相应类的对象,运行类型为com.hly.reflection.Cat
    Object o = aClass.newInstance();
    // 获取类相关信息,直接获取的只有公有成员
    // 通过类加载对象获取相应的方法
    Method method = aClass.getMethod(methodName);

    //调用方法,方法.invoke(对象) 反射相当于一面镜子,这个方法很形象
    method.invoke(o);

    //获取公有的成员属性,不能直接获取私有成员,需要通过转化获取
    Field age = aClass.getField("age");
    //Filed 返回类的属性字段
    System.out.println(age);

    // 获取构造器,通过只能参数个数和类型.class来获取构造器
    Constructor<?> constructor = aClass.getConstructor();// 无参构造器
    System.out.println(constructor);
    //有参构造
    // 注意八大基本数据类型,不是.class,而是.TYPE
    Constructor<?> constructor1 = aClass.getConstructor(Double.TYPE, String.class);
    System.out.println(constructor1);
}

获取类的结构信息

基本api

@Test
public static void api01() throws ClassNotFoundException {

    //获取类对象
    Class<?> PersonClass = Class.forName("com.hly.class_.Person");

    // 获取类的public属性,包括本类和父类
    Field[] fields = PersonClass.getFields();
    for (Field field : fields) {
        System.out.println("该类和父类的所有公有属性="+field.getName());
    }
    // 获取本类所有属性
    Field[] declaredFields = PersonClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        System.out.println("本类的所有属性="+declaredField.getName());
    }

    // 获取该类的public方法,包括父类
    Method[] methods = PersonClass.getMethods();
    for (Method method : methods) {
        System.out.println("所有的公有方法="+method.getName());
    }
    // 本类的所有方法
    Method[] declaredMethods = PersonClass.getDeclaredMethods();
    for (Method declaredMethod : declaredMethods) {
        System.out.println("所有的方法="+declaredMethod.getName());
    }

    // 获取本类的public构造器,不包括父类
    Constructor<?>[] constructors = PersonClass.getConstructors();
    for (Constructor<?> constructor : constructors) {
        System.out.println("public构造器="+constructor);
    }
    // 本类的所有构造器
    Constructor<?>[] declaredConstructors = PersonClass.getDeclaredConstructors();
    for (Constructor<?> declaredConstructor : declaredConstructors) {
        System.out.println("所有的构造器="+declaredConstructor);
    }

    //获取本类的接口
    Class<?>[] interfaces = PersonClass.getInterfaces();
    for (Class<?> anInterface : interfaces) {
        System.out.println("接口="+anInterface.getName());
    }

    // 获取本类的接口
    Annotation[] annotations = PersonClass.getAnnotations();
    for (Annotation annotation : annotations) {
        System.out.println("注解="+annotation);
    }

}

}
class A{
    public int Ajob;

    public void am1(){};

}

interface IA{}
interface IB{}
//Person类
@Deprecated
class Person extends A implements IA,IB{
    public String job;
    private int age;
    String name;
    protected String sex;

    public Person(){}
    private Person(int age){}
    Person(String name){}
    protected Person(String job,String sex){}


    public String m1(int age){return null;}
    private String m2(String name){return null;}
    void m3(){}
    protected void m4(){}
}

Filed

//获取类对象
Class<?> PersonClass = Class.forName("com.hly.class_.Person");

// 修饰符: 默认 0 public 1 private 2 protected 4 final 4 static 8
// 组合类型为 对应相加
Field[] declaredFields = PersonClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
    System.out.println("本类的所有属性="+declaredField.getName()+" 修饰符= "+declaredField.getModifiers()+
                       " 类型="+declaredField.getType());
}

Method

// 本类的所有方法
Method[] declaredMethods = PersonClass.getDeclaredMethods();
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.getName());
    }
}

Constructor

// 构造器
Constructor<?>[] declaredConstructors = PersonClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
    System.out.println("所有的构造器="+declaredConstructor+" 修饰符="+declaredConstructor.getModifiers()
                      );
    System.out.println("形参列表:");
    Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
    for (Class<?> parameterType : parameterTypes) {

        System.out.println(parameterType.getName());

    }
}

爆破获取类的结构信息

Filed

public class ReflectFiled {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<?> aClass = Class.forName("com.hly.reflection.Boss");

        Object o = aClass.newInstance();

        // 获取公有属性
        Field name = aClass.getField("name");
        // 设置属性
        name.set(o,"hly");
        System.out.println(o);

        //获取私有属性
        Field age = aClass.getDeclaredField("age");
        //爆破
        age.setAccessible(true);
        age.set(o,19);
        System.out.println(o);

        //如果是static,则对象可以为null,或者是类的对象实例
        Field sex = aClass.getDeclaredField("sex");
        sex.setAccessible(true);
        sex.set(null,"女");

        System.out.println(o);
    }
}

class Boss{
    private int age;
    public String name;
    private static String sex;
    public Boss(){};

    @Override
    public String toString() {
        return "Boss{" +
            "age=" + age +
            ", name='" + name + '\'' +
            '}'+"sex="+sex;
    }
}

Method

  1. 与属性操作类似
  2. aClass.getDeclaredMethod("xx方法名",参数列表.class);

反射机制

反射优点和缺点

  1. 优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑
  2. 缺点:使用反射基本是解释执行,对执行速度有影响

优化

Field、Method、Constructor通过设置setAccessible()为true可以关闭访问执行时安全检测,提高执行速度.默认为false,即开启检测。提高不是很明显。