JAVA反射机制

前言

java的反射机制就是在运行状态中,对于任意一个类,如果我们都能调用它的任意方法和属性,那么我们就可以修改部分类型信息。这种动态获取信息以及动态调用对象方法的功能称为反射机制。我们经常会遇到某个类的成员变量、方法或是属性是私有的,如果要获取这些私有的方法或成员我们就需要用到反射技术。反射最重要的用途就是开发各种通用框架。

1、反射相关的类

类名用途
Class类代表类的实体,在运行的java应用程序中表示类和接口
Field类代表类的成员变量/类的属性
Method类代表类的方法
Constructor类代表类的构造方法
1.1 Class类中常用方法
方法用途
getClassLoader()获得类的加载器
getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口的对象
forName()根据类名返回类的对象
newInstance()创建类的实例
getName()获得类的完整路径名称
1.2 Filed类中常用方法
方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象
1.3 Method类中常用方法
方法用途
getMethod(String name,Class…<?>parameterTypes)获得该类某个公有的方法
getMethods()获得该类所有公有的方法
getDeclaredMethod(String name,Class…<>parameterTypes)获得该类某个方法
getDeclaredMethods()获得该类所有方法
1.4 Constructor类中常用方法
方法用途
getConstructor(Class…<?>parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructs()获得该类的所有公有构造方法
getDeclaredConstructor(Class…<?>parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法

注意:以上方法中,含有Declared指可以访问类的所有的方法,包括私有方法。而没有Declared的方法只能访问类的公有方法,即public方法。

2、反射示例

获得Class对象的三种方式:

  • Class.forName(“类的全路径名”)
  • .class方法
  • getClass()方法

示例:

class Student{
    private String name = "小汤姆";
    public int age = 12;
    public Student() {
        System.out.println("无参构造方法");
    }
    private Student(String name) {
        this.name = name;
    }
    public Student(int age) {
        this.age = age;
    }

    private Student(String name,int age) {
        this.name = name;
        this.age = age;
    }
    
    private void eat(String  name) {
        System.out.println(name + "eating");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Class<?> aClass = null;
        //Class.forName()
        try {
            aClass = Class.forName("ReflectDemo.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //.class
        Class<Student> studentClass = Student.class;
        //getClass()
        Student student = new Student();
        Class<? extends Student> studentClass1 = student.getClass();

        //三种方式获得的都是同一个Student对象
        System.out.println(studentClass == studentClass1);  //true
        System.out.println(aClass == studentClass);  //true
        System.out.println(aClass == studentClass1); //true
    }

}

3、反射的使用

    public static void  reflectNewInstance() {
        //通过反射创建Student实例
        Class<?> aClass = null;
        try {
            aClass = Class.forName("ReflectDemo.Student");
            Object o = aClass.newInstance();
            Student student = (Student) o;
            System.out.println("学生对象 :" + student);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

//通过反射修改私有的属性
    public static void reflectField(){
        Class<?> aClass = null;
        try {
            aClass = Class.forName("ReflectDemo.Student");
            Field field = aClass.getDeclaredField("name");   //访问私有属性,name

            field.setAccessible(true);   //更改权限,让我们可以修改该属性

            Object o = aClass.newInstance();  //创建实例   我们的实例默认name = 小汤姆 age = 12
            Student student = (Student) o;

            field.set(student,"小红果");  //设置name属性
            String name  = (String) field.get(student);
            System.out.println("反射私有属性,并修改为 :" + name);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//通过反射访问私有方法
    public static void refleftMethod() {
        try {
            Class<?> aClass = Class.forName("ReflectDemo.Student");
            Method method = aClass.getDeclaredMethod("eat", String.class); //访问私有方法
            System.out.println("私有方法: " + method.getName());

            method.setAccessible(true);  //更改权限

            Object o = aClass.newInstance();  //创建实例
            Student student = (Student) o;

            method.invoke(student,"反射私有方法,创建实例,调用私有方法,传递参数");  //invoke调用方法

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

//通过反射访问私有的构造方法
    public static  void reflectConstructor() {
        try {
            Class<?> aClass = Class.forName("ReflectDemo.Student");
            Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class,int.class);  //私有构造方法有两个参数
            declaredConstructor.setAccessible(true);  //修改权限

            Object o = declaredConstructor.newInstance("小花", 18);  //用构造方法创建实例

            Student student = (Student) o;
            System.out.println("获得私有构造函数并创建实例:" + student);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

4、反射的优缺点

优点:

  • 对于任意一个类,都能够知道这个类的所有属性和方法;对于一个对象,都能够调用它的任意一个方法
  • 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
  • 反射已经应用在很多流行框架中如:Struts、Spring等

缺点:

  • 有效率问题,会导致程序效率降低
  • 反射绕过了源码,会带来维护问题(反射本身就相当于篡改)
  • 反射的代码比相应的直接代码更加复杂
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值