JAVA每日经典面试题

Java 高级面试问题及答案

问题1: 在Java中,什么是强引用、软引用、弱引用和虚引用?它们之间有什么区别?

答案:
在Java中,引用分为四种类型:

  • 强引用:如果对象具有强引用,那么它永远不会被垃圾回收器回收。
  • 软引用:软引用关联的对象在内存不足时会被回收,可以通过java.lang.ref.SoftReference类来实现。
  • 弱引用:弱引用的对象只能生存到下一次垃圾回收发生时,无论内存空间是否充足,都可以被回收,使用java.lang.ref.WeakReference类。
  • 虚引用:一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获取一个对象的实例,使用java.lang.ref.PhantomReference类。

它们之间的主要区别在于垃圾回收器对它们的态度和回收时机。

问题2: 请解释Java中的类加载器(ClassLoader)以及它的工作机制。

答案:
Java中的类加载器负责将.class文件加载到JVM中。类加载器是Java运行时环境的一部分,用于动态加载Java类文件。Java类加载机制主要涉及以下几个方面:

  • 加载:查找.class文件并将其加载到JVM中。
  • 链接:验证.class文件的字节码,并为类分配内存空间。
  • 初始化:执行类构造器<clinit>()方法,进行静态变量的初始化。

类加载器的层次结构通常包括:

  • 启动类加载器(Bootstrap ClassLoader):负责加载核心Java类库。
  • 扩展类加载器(Extension ClassLoader):负责加载扩展库。
  • 应用程序类加载器(Application ClassLoader):负责加载应用程序类路径上的类。

问题3: 如何在Java中实现单例模式?请说明其线程安全问题及解决方案。

答案:
单例模式确保一个类只有一个实例,并提供一个全局访问点。以下是实现单例模式的一种方式:

public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

线程安全问题:在多线程环境下,如果多个线程同时调用getInstance()方法,可能会创建多个实例。

解决方案

  1. 懒汉式加锁:如上例,使用synchronized关键字确保线程安全,但影响性能。
  2. 饿汉式:在类加载时就创建实例,简单但不延迟加载。
  3. 静态内部类:利用Java的类加载机制,实现线程安全的单例模式,延迟加载。
  4. 枚举:使用Java枚举实现单例,具有天然的线程安全性和防止反序列化创建新实例的特点。

问题4: 描述Java中的代理模式,并给出一个使用动态代理的示例。

答案:
代理模式(Proxy Pattern)是一种设计模式,它允许为其他对象提供一个代理或占位符,以控制对这个对象的访问。Java中的动态代理使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口实现。

示例

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 目标对象接口
interface Service {
    void execute();
}

// 目标对象实现
class RealService implements Service {
    public void execute() {
        System.out.println("Executing real service.");
    }
}

// 动态代理类
class ProxyHandler implements InvocationHandler {
    private Object target;

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

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before execution.");
        method.invoke(target, args);
        System.out.println("After execution.");
        return null;
    }
}

public class ProxyDemo {
    public static void main(String[] args) {
        RealService realService = new RealService();
        Service proxy = (Service) java.lang.reflect.Proxy.newProxyInstance(
                realService.getClass().getClassLoader(),
                new Class[]{Service.class},
                new ProxyHandler(realService)
        );

        proxy.execute();
    }
}

在这个示例中,ProxyHandlerInvocationHandler的实现,它包装了对RealService对象的调用,ProxyDemo展示了如何使用动态代理来包装一个服务对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值