Java反射机制 反射的优缺点?

什么是Java的反射?
  在运行状态中,对于任意一个类,都能够知道这个类的属性和方法;

反射的作用?
  如果给定一个类名,就可以通过反射机制来获取类的所有信息,也可以动态的创建对象和编译;

反射的原理?
  Java语言在编译之后会生成一个class文件,反射就是通过字节码文件找到其类中的方法和属性等;
反射的实现主要借助以下四个类:
1、Class:类的对象;
2、Constructor:类的构造方法
3、Field:类中的属性对象
4、Method:类中的方法对象

创建一个对象

Class class = Class.forname(XXX);
Student student = (Student)class.newInstance();

获取类中的所有方法 Mehod

public static void main(String[] args) {
    try {
        Class<?> clz = Class.forName("fs.Student");
        Method[] methods = clz.getMethods();
        for (Method method : methods) {
            System.out.println("方法名:" + method.getName());
        }
    } catch (ClassNotFoundException e) {
            e.printStackTrace();
    }
}
  • Class.forName("fs.Student"):初始化指定的类
  • clz.getMethods():获取类中所有的方法(包括其继承类的方法)
  • class.getMethod(方法名,参数类型.class)

如果只需要获取加载类中的方法,不要父类的方法,可以使用下面的代码:

Method[] methods = clz.getDeclaredMethods();

Method是方法类,可以获取方法相关的信息,除了我们上面的方法名称,我们还可以获取其他的一些信息,比如:

  • 方法返回类型:method.getReturnType().getName()
  • 方法修饰符:Modifier.toString(method.getModifiers())
  • 方法参数信息: method.getParameters()
  • 方法上的注解: method.getAnnotations()

操作方法(invoke 对象名 参数)

try {
    Class<?> clz = Class.forName("fs.Student");
    Student stu = (Student) clz.newInstance();
    System.out.println(stu.getName());
    Method method = clz.getMethod("setName", String.class);
    method.invoke(stu, "猿天地");
    System.out.println(stu.getName());
} catch (Exception e) {
    e.printStackTrace();
} 

获取类中的所有属性(Field)

Class<?> clz = Class.forName("fs.Student");
Field[] fields = clz.getFields();
for (Field field : fields) {
    System.out.println("属性名:" + field.getName());
}

clz.getFields()只能获取public的属性,包括父类的。

如果需要获取自己声明的各种字段,包括public,protected,private得用clz.getDeclaredFields()

Field是属性类,可以获取属性相关的信息,比如:

  • 属性类型:field.getType().getName()
  • 属性修饰符:Modifier.toString(field.getModifiers())
  • 属性上的注解: field.getAnnotations()
操作属性
try {
    Class<?> clz = Class.forName("fs.Student");
    Student stu = (Student) clz.newInstance();
    Field field = clz.getDeclaredField("name");
    field.setAccessible(true);
    System.out.println(field.get(stu));
    field.set(stu, "猿天地");
    System.out.println(field.get(stu));
} catch (Exception e) {
    e.printStackTrace();
} 

field.setAccessible(boolean):;以取消Java的权限控制检查,让我们在用反射时可以访问访问私有变量

field.set(对象名,参数)

优点

  • 反射提高了程序的灵活性和扩展性,在底层框架中用的比较多,业务层面的开发过程中尽量少用。

缺点

  • 性能不好
    反射是一种解释操作,用于字段和方法接入时要远慢于直接代码,下面通过2段简单的代码来比较下执行的时间就可以体现出性能的问题