Java反射面试总结(一)

什么是反射?

Java的反射是指在程序运行时,对于任意一个类,都可以获取到这个类的所有属性和方法,并能够对其进行操作。通过反射机制,可以在程序运行时动态地创建对象、调用方法、获取属性值等。反射可以帮助我们更轻松地实现一些复杂的功能,但也会带来一些性能上的损失。

Java反射机制的基本步骤:

  1. 获取Class对象:通过反射可以动态地获取类对象,即Class对象。Class对象是Java运行时系统中的一个重要概念,每个类都有一个与之对应的Class对象,通过Class对象可以获取类的所有信息。

示例代码:

Class clazz = Class.forName("java.lang.String"); // 获取String类的Class对象
  1. 创建对象:通过Class对象可以实例化一个具体的对象。

示例代码:

Object obj = clazz.newInstance(); // 实例化一个String对象
  1. 访问属性:通过反射可以获取和设置对象的属性,包括公共的和私有的。

示例代码:

Field field = clazz.getField("value"); // 获取value属性
Object value = field.get(strObj); // 获取value属性的值
field.set(strObj, newValue); // 设置value属性的值为newValue
  1. 调用方法:通过反射可以调用对象的方法,包括公共的和私有的。

示例代码:

Method method = clazz.getMethod("substring", int.class, int.class); // 获取substring方法
Object result = method.invoke(strObj, startIndex, endIndex); // 调用substring方法,传递参数startIndex和endIndex
  1. 执行构造函数:通过反射可以调用对象的构造函数来实例化对象。

示例代码:

Constructor constructor = clazz.getConstructor(String.class); // 获取含有一个String类型参数的构造函数
Object obj = constructor.newInstance("Hello, World!"); // 调用构造函数并实例化对象

Java的反射机制带来了很多便利,但同时也会损失一些性能,在使用时需要慎重考虑其是否真正必要。

反射的应用场景了解么?

像咱们平时大部分时候都是在写业务代码,很少会接触到直接使用反射机制的场景。但是!这并不代表反射没有用。相反,正是因为反射,你才能这么轻松地使用各种框架。像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。

这些框架中也大量使用了动态代理,而动态代理的实现也依赖反射。

比如下面是通过 JDK 实现动态代理的示例代码,其中就使用了反射类 Method 来调用指定的方法。

public class DebugInvocationHandler implements InvocationHandler {
    /**
     * 代理类中的真实对象
     */
    private final Object target;

    public DebugInvocationHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        System.out.println("before method " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("after method " + method.getName());
        return result;
    }
}

另外,像 Java 中的一大利器 注解 的实现也用到了反射。为什么你使用 Spring 的时候 ,一个@Component注解就声明了一个类为 Spring Bean 呢?为什么你通过一个 @Value注解就读取到配置文件中的值呢?究竟是怎么起作用的呢?这些都是因为你可以基于反射分析类,然后获取到类/属性/方法/方法的参数上的注解。你获取到注解之后,就可以做进一步的处理。

反射在Java中是一种高级的语言特性,它允许程序在运行时动态地获取类的信息、访问和操作类的属性和方法等。因此,它的应用场景非常广泛,以下是一些例子:

  1. 框架开发:许多框架(如Spring)利用反射获取类的信息和属性,来实现依赖注入、控制反转等功能。

  2. 动态代理:利用反射机制来动态生成代码,从而实现对某些对象的代理。

  3. 注解解析:通过反射来获取类、方法、字段等的注解信息。

  4. Java序列化:反射机制使得可以在编译时未知的情况下,将对象序列化为字节流,然后再通过反射将字节流转换成对象。

  5. 反编译工具:反编译工具利用反射实现对Java代码的分析和探测,可以查看方法、字段的信息以及代码的执行流程等。

总之,反射机制是Java语言中非常有用的一种特性,能够极大地提高程序的可扩展性、灵活性和可维护性。

反射机制的优缺点有哪些?

优点

  1. 动态性:能够运行时动态获取类的信息,访问和操作类的属性和方法,提高了灵活性;例如可与动态编译结合 Class.forName(‘com.mysql.jdbc.Driver.class’),加载MySQL的驱动类;
  2. 适应性:反射机制不依赖于具体的硬件、操作系统和JVM,可以应用于任何Java程序中;
  3. 灵活性:反射机制提供了更灵活的编程方式,可以在不知道具体的类名的情况下,创建对象、调用方法等。

缺点

  1. 性能问题:使用反射性能较低,需要解析字节码,将内存中的对象进行解析。其解决方案是:通过 setAccessible(true) 关闭JDK的安全检查来提升反射速度;
  2. 安全问题:反射机制可以访问和修改对象的私有属性和方法,有可能会破坏程序的安全性和稳定性,因此必须谨慎使用;
  3. 可读性问题:反射机制动态调用方法和属性,代码可读性较差,不容易维护和调试。

总之,优点就是动态获取类信息,操作类的属性和方法们这是核心,缺点无非就是性能、安全和可读性,一定不要死记硬背,要通过原理去理解。

如何获取反射中的Class对象?

  1. Class.forName(“类的路径”);当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。
Class clz = Class.forName("java.lang.String");
  1. 类名.class。这种方法只适合在编译前就知道操作的 Class。
Class clz = String.class;
  1. 对象名.getClass()。
String str = new String("Hello");
Class clz = str.getClass();
  1. 如果是基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象。

除了上述几种种方法,还可以通过ClassLoader类的loadClass()方法来获取Class对象,这种方式常用于加载外部或动态生成的类。

Java反射API有几类?

反射 API 用来生成 JVM 中的类、接口或则对象的信息。

  1. Class 类:反射的核心类,可以获取类的属性,方法等信息。

  2. Field 类:Java.lang.reflect 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。

  3. Method 类:Java.lang.reflect 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。

  4. Constructor 类:Java.lang.reflect 包中的类,表示类的构造方法。

反射使用的步骤?

  1. 获取想要操作的类的Class对象,这是反射的核心,通过Class对象我们可以任意调用类的方法。

  2. 调用 Class 类中的方法,既就是反射的使用阶段。

  3. 使用反射 API 来操作这些信息。

具体可以看下面的例子:

public class Student {

    private Integer age;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public static void main(String[] args) {

        //正常调用
        Student student = new Student();
        student.setAge(16);
        System.out.println("Student Age : " + student.getAge());

        //使用反射调用
        try {
            Class<?> aClass = Class.forName("com.lzl.javaSE.test8.Student");
            Method setAge = aClass.getMethod("setAge", Integer.class);
            Constructor<?> studentConstructor = aClass.getConstructor();
            Object studentObject = studentConstructor.newInstance();
            setAge.invoke(studentObject, 18);
            Method getAge = aClass.getMethod("getAge");
            System.out.println("Student Age : " + getAge.invoke(studentObject));

        } catch (ClassNotFoundException | InstantiationException | InvocationTargetException | NoSuchMethodException |
                 IllegalAccessException e) {
            throw new RuntimeException(e);
        }


    }
}

从代码中可以看到我们使用反射调用了 setAge方法,并传递了 16 的值。之后使用反射调用了 getAge 方法,输出其年龄。上面的代码整个的输出结果是:

Student Age : 16
Student Age : 18

从这个简单的例子可以看出,一般情况下我们使用反射获取一个对象的步骤:

  • 获取类的 Class 对象实例
Class<?> aClass = Class.forName("com.lzl.javaSE.test8.Student");
  • 根据 Class 对象实例获取 Constructor 对象
Constructor<?> studentConstructor = aClass.getConstructor();
  • 使用 Constructor 对象的 newInstance 方法获取反射类对象
Object studentObject = studentConstructor.newInstance();

而如果要调用某一个方法,则需要经过下面的步骤:

  • 获取方法的 Method 对象
Method setAge = aClass.getMethod("setAge", Integer.class);
  • 利用 invoke 方法调用方法
setAge.invoke(studentObject, 18);

使用反射拿到私有属性值

Java通过反射机制可以获取和操作类、方法、字段等信息。在Java中,私有属性对外不可见,因此不能直接访问私有属性的值。但是,我们可以使用反射机制来绕过访问限制,获取私有属性的值。

下面是获取私有属性值的示例代码:

import java.lang.reflect.Field;

public class PrivateFieldTest {
    private String privateField = "private value";

    public static void main(String[] args) throws Exception {
        PrivateFieldTest obj = new PrivateFieldTest();

        // 获取私有属性对象
        Field field = PrivateFieldTest.class.getDeclaredField("privateField");
        // 设置可访问私有属性
        field.setAccessible(true);
        // 获取私有属性值
        String value = (String) field.get(obj);
        // 输出私有属性值
        System.out.println("privateField value: " + value);
    }
}

在上面的示例代码中,我们首先定义了一个私有属性privateField,然后在main方法中通过反射机制获取privateField的值。这里要注意,我们要通过类的getDeclaredField方法获取私有属性对象,并且要将其设置为可访问状态。

另外,我们还需要调用Field类的get方法获取私有属性的值,其中第一个参数是对象实例,表示要获取该对象中的私有属性值。最后我们将获取到的私有属性值输出。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当涉及到Java高级开发面试题时,以下是些常见的问题和答案: 1. 什么是Java反射机制? Java反射机制允许程序在运行时动态地获取类的信息并操作类的成员。通过反射,可以在运行时创建对象、调用方法、访问字段等。 2. 什么是Java的泛型? Java的泛型是一种参数化类型的概念,它允许在编译时指定类或方法可以操作的数据类型,提高代码的重用性和类型安全性。 3. 什么是Java的注解? Java的注解是一种元数据,它可以用于给程序中的代码添加额外的信息。注解可以用于编译时进行静态检查、运行时进行动态处理,或者生成额外的代码。 4. 什么是Java的多线程? Java的多线程是指在一个程序中同时执行多个线程,每个线程都有自己的执行路径。多线程可以提高程序的并发性和响应性。 5. 什么是Java的异常处理机制? Java的异常处理机制允许程序在出现错误或异常情况时进行处理,以保证程序的正常执行。通过try-catch语句块,可以捕获并处理异常,避免程序崩溃。 6. 什么是Java的IO流? Java的IO流是用于处理输入和输出的机制。它提供了一组类和接口,用于读取和写入数据。IO流可以用于文件操作、网络通信等。 7. 什么是Java的集合框架? Java的集合框架是一组用于存储和操作数据的类和接口。它提供了各种数据结构,如列表、集合、映射等,以及对这些数据结构进行操作的方法。 8. 什么是Java的设计模式? Java的设计模式是一套被广泛应用于软件开发中的解决问题的经验总结。它提供了一些常见的设计思想和模式,如单例模式、工厂模式、观察者模式等。 9. 什么是JavaJVMJavaJVMJava Virtual Machine)是Java虚拟机的缩写,它是Java程序运行的环境。JVM负责将Java字节码转换为机器码,并提供内存管理、垃圾回收等功能。 10. 什么是Java的并发编程? Java的并发编程是指在多线程环境下编写程序,以实现并发执行和共享资源的安全访问。Java提供了一些并发编程的工具和类,如锁、条件变量、线程池等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上阡陌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值