You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java泛型父类实现GetInstance出现StackOverflowError问题求助

解决单例实现中的StackOverflowError问题

嘿,我一眼就看出你代码里的问题啦——这是典型的无限递归导致栈溢出!咱们来拆解一下:

问题根源

你写的Instance类构造函数里,居然又调用了new Instance<>():

public <T> Instance() {
    mInstance = new Instance<>();
}

这就相当于,每次创建Instance对象时,构造函数会立刻再创建一个新的Instance,新的对象构造又会再创建一个……无限循环下去,Java虚拟机的调用栈被不断压满,最终就抛出了java.lang.StackOverflowError,也就是你看到的崩溃。

而且你这段代码的逻辑也偏离了单例的初衷:单例是要保证一个类只有一个实例,你现在反而在不断创建新实例,还把构造函数设为了公有的,外部也能随便new,完全不符合单例的设计。

修正方案:实现正确的泛型单例

根据你的需求,我给你两种常见的泛型单例实现方式,你可以根据场景选择:

方式1:所有子类共享父类的单例实例

如果你的所有子类(比如Timer)只需要共用一个父类的单例,那可以用**双重检查锁定(DCL)**来实现,保证线程安全且性能不错:

public class Instance<T> {
    // volatile关键字避免多线程下的指令重排问题
    private static volatile Instance<?> mInstance;

    // 私有构造函数,禁止外部直接创建实例
    protected Instance() {}

    @SuppressWarnings("unchecked")
    public static <T> Instance<T> GetInstance() {
        // 双重检查,减少锁竞争
        if (mInstance == null) {
            synchronized (Instance.class) {
                if (mInstance == null) {
                    mInstance = new Instance<>();
                }
            }
        }
        return (Instance<T>) mInstance;
    }
}

public class Timer extends Instance<Timer> {
    // 子类可以直接继承父类的单例逻辑,无需额外代码
}

// 使用方式
Timer timerInstance = (Timer) Instance.GetInstance();

方式2:每个子类拥有自己的独立单例

如果你的需求是每个子类(比如Timer)都有自己的唯一实例,那上面的方式就不适用了(因为父类静态变量是所有子类共享的)。这种情况下可以用ConcurrentHashMap来存储每个子类的实例:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Instance<T> {
    // 用线程安全的Map存储每个子类的实例
    private static final Map<Class<?>, Instance<?>> INSTANCE_CACHE = new ConcurrentHashMap<>();

    // 构造函数设为protected,允许子类继承
    protected Instance() {}

    @SuppressWarnings("unchecked")
    public static <T> Instance<T> GetInstance(Class<T> clazz) {
        // computeIfAbsent:如果缓存里没有对应实例,就创建并放入缓存
        return (Instance<T>) INSTANCE_CACHE.computeIfAbsent(clazz, cls -> {
            try {
                // 通过反射创建子类实例,要求子类有可访问的无参构造
                return (Instance<?>) cls.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new RuntimeException("无法创建" + cls.getName() + "的实例", e);
            }
        });
    }
}

public class Timer extends Instance<Timer> {
    // 子类的构造函数可以设为protected或private(private的话需要允许反射访问)
    protected Timer() {}
}

// 使用方式
Timer timerInstance = (Timer) Instance.GetInstance(Timer.class);

额外注意点

  • 原来代码里构造函数上的<T>是多余的,会和类的泛型<T>冲突,直接去掉就好
  • 单例模式一定要保证构造函数私有/受保护,避免外部随意创建实例
  • 如果是多线程场景,一定要考虑线程安全问题,不然可能会创建多个实例

内容的提问来源于stack exchange,提问作者ManLok Wong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:47:27