Java反射机制

一、反射的定义

  首先我们需要知道什么是动态语言,动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。比如常见的 JavaScript 就是动态语言,除此之外Ruby、Python 等也属于动态语言,而 C、C++则不属于动态语言。从反射角度说 JAVA 属于半动态语言。

  Java的反射(reflection)机制是说,**在运行状态中,对于任意一个类都能知道它的所有属性和方法,并且对于任意一个对象,都能调用它的所有方法,**这种动态获取信息以及动态调用对象方法的机制就被称为反射。

二、反射的作用

  反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。总结一句话就是:反射是框架设计的灵魂

三、反射的原理

  在前面讲类加载机制时提到,在类加载的第一步时,JVM就会在内存中根据.Class文件生成一个Class对象,这个对象里面就储存了这个类的全部信息,反射的第一步就是获取这个Class对象,然后通过Class类(这是一个类型,每个类的Class对象的类型就是Class)中提供的方法来获取这个类中的所有方法、属性。

1、获取Class对象

获取Class对象的方式有三种:

1、通过类名.class的方式获取

2、通过对象的getClass()方法获取

3、通过 Class 对象的 forName() 静态方法来获取,用的最多,但可能抛出 ClassNotFoundException 异常

public static void main(String[] args) {
        //第一种方式
        Class c1 = Student.class;

        //第二种方式
        Student student = new Student();
        Class c2 = student.getClass();

        //第三种方式
        Class c3 = null;
        try {
            //注意这里是类的全路径,如果有包需要加包的路径  
            c3 = Class.forName("Student");
        } catch (ClassNotFoundException classNotFoundException) {
            classNotFoundException.printStackTrace();

        }
        System.out.println(c1==c2);
        System.out.println(c2==c3);
        System.out.println(c1==c3);
    }
    ——————————————————————————————————————————————————————————————————————————
结果    true
        true
        true

一个类只有一个Class对象,不管是什么方法,获得的都是同一个对象。

2、其他常见的类

  • Java.lang.reflect.Constructor,相当于是一个类的构造方法
方法名用途
Constructor getConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的公有构造方法
Constructor[ ] getConstructors()获得该类的所有公有构造方法
Constructor getDeclaredConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的构造方法
Constructor[ ] getDeclaredConstructors()获得该类所有构造方法
  • Java.lang.reflect.Field,相当于是一个类的字段属性
方法名用途
Field getField(String name)获得某个公有的属性对象
Field[ ] getFields()获得所有公有的属性对象
Field getDeclaredField(String name)获得某个属性对象
Field[ ] getDeclaredFields()获得所有属性对象
  • Java.lang.reflect.Method,相当于是一个类的方法
Method getMethod(String name, Class…<?> parameterTypes)获得该类某个公有的方法
Method[ ] getMethods()获得该类所有公有的方法
Method getDeclaredMethod(String name, Class…<?> parameterTypes)获得该类某个方法
Method[ ] getDeclaredMethods()获得该类所有方法

具体使用

class Student{
    //私有属性name
    private String name = "bit";
    //公有属性age
    public int age = 18;
    //不带参数的构造方法
    public Student(){
        System.out.println("Student()");
    }
    private Student(String name,int age) {
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }
    private void eat(){
        System.out.println("i am eat");
    }
    public void sleep(){
        System.out.println("i am pig");
    }
    private void function(String str) {
        System.out.println(str);
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test11 {
    //获取私有构造方法
    public static void reflectPrivateConstructor() {
        try {
            Class studentclass = Class.forName("Student");
            Constructor constructor = studentclass.getDeclaredConstructor(String.class,int.class);
            constructor.setAccessible(true);
            Object object = constructor.newInstance("zhangsan",18);
            Student student = (Student)object;
            System.out.println(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	//获取私有属性
    public static void  reflectPrivateField(){
        try {
            Class studentclass = Class.forName("Student");
            Field field = studentclass.getDeclaredField("name");
            field.setAccessible(true);
            Object object =studentclass.newInstance();
            Student student = (Student)object;
            field.set(student,"王五");
            String name = (String) field.get(student);
            System.out.println(name);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    //获取私有有参数的私有方法
    public static void reflectPrivateMethod(){
        try {
            Class studentclass = Class.forName("Student");
            Method method = studentclass.getDeclaredMethod("function",String.class);
            System.out.println(method.getName());
            method.setAccessible(true);
            Object object = studentclass.newInstance();
            Student student = (Student)object;
            method.invoke(student,"i am student");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    //获取无参数的私有方法
    public static void reflectPrivateEat(){
        try {
            Class studentclass =  Class.forName("Student");
            Method method = studentclass.getDeclaredMethod("eat");
            System.out.println(method.getName());
            Object object = studentclass.newInstance();
            Student student = (Student) object;
            method.setAccessible(true);
            method.invoke(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        reflectPrivateConstructor();
        reflectPrivateField();
        reflectPrivateMethod();
        reflectPrivateEat();
    }
}

四、反射的优缺点

优点:

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

缺点:

  1. 使用反射会有效率问题。会导致程序效率降低。
  2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值