2025java常见面试题第二弹

1. Java中的#{}${}的区别是什么?

答案#{}${}在Java中主要用于模板引擎或框架中,如MyBatis等,它们的区别如下:

  • ${}

    • 是OGNL表达式的一部分,用于直接替换变量值。

    • 不会进行类型转换,直接将变量的值作为字符串拼接到SQL语句中。

    • 如果变量值为null,可能会导致SQL语句拼接错误。

  • #{}

    • 是MyBatis的占位符,用于预编译SQL语句。

    • 支持类型转换,会将变量值作为参数传递给预编译的SQL语句。

    • 如果变量值为null,会自动处理为NULL,避免SQL语句出错。

适用场景

  • 使用${}时,需要确保变量值不为null,且拼接后的SQL语句语法正确。

  • 使用#{}时,更适合处理可能为null的变量,同时支持预编译,提高SQL执行效率。

2. Java中如何实现动态代理?

答案: 动态代理是一种在运行时动态生成代理类的技术,通常用于实现AOP(面向切面编程)。Java中可以通过java.lang.reflect.Proxy类和InvocationHandler接口来实现动态代理。

实现步骤

  1. 定义接口: 定义一个接口,声明需要代理的方法。

    java复制

    public interface MyService {
        void doSomething();
    }
  2. 实现InvocationHandler接口: 创建一个InvocationHandler实现类,用于处理代理方法的调用。

    java复制

    import java.lang.reflect.*;
    
    public class MyInvocationHandler implements InvocationHandler {
        private final Object target;
    
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 在方法调用前后添加逻辑
            System.out.println("Before method: " + method.getName());
            Object result = method.invoke(target, args);
            System.out.println("After method: " + method.getName());
            return result;
        }
    }
  3. 生成代理对象: 使用Proxy.newProxyInstance()方法动态生成代理对象。

    java复制

    public class DynamicProxyDemo {
        public static void main(String[] args) {
            MyService target = new MyServiceImpl(); // 目标对象
            MyInvocationHandler handler = new MyInvocationHandler(target);
    
            MyService proxy = (MyService) Proxy.newProxyInstance(
                MyService.class.getClassLoader(), // 目标类的类加载器
                new Class<?>[]{MyService.class}, // 目标类实现的接口
                handler // InvocationHandler实例
            );
    
            proxy.doSomething(); // 调用代理方法
        }
    }

应用场景

  • 动态代理常用于Spring的AOP功能,如事务管理、日志记录等。

3. Java中String为什么是不可变的?

答案String在Java中是不可变的,这意味着一旦创建了一个String对象,它的内容就不能被修改。

原因

  1. 线程安全

    • 不可变性使得String对象在多线程环境中不需要额外的同步措施,因为它的状态不会改变。

  2. 性能优化

    • JVM可以利用字符串常量池,对相同的字符串值进行共享,减少内存占用。

  3. 安全性

    • 不可变性使得String对象可以被用作类加载器的加载路径或作为HashMap的键,确保其值不会被意外修改。

实现原理

  • String类的内部使用一个字符数组char[]来存储字符串内容,该数组被声明为final,且在构造函数中初始化后无法修改。

  • 所有修改字符串的操作(如substring()concat()等)都会返回一个新的String对象。

示例

java复制

String str1 = "Hello";
String str2 = str1.concat(" World");
System.out.println(str1); // 输出 "Hello",原字符串未被修改
System.out.println(str2); // 输出 "Hello World",返回了新的字符串对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值