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

如何使类A及其任意子类通过new仅能创建单实例?(总监四轮面试题)

Great question! Let's tackle this problem step by step. The goal is to ensure that both the base class A and any of its subclasses can only be instantiated once via the new keyword—with an exception thrown on subsequent attempts—and all enforcement logic lives inside the class hierarchy, not the main method.

Solution Code

First, here's the implementation for the base class A:

import java.util.HashSet;
import java.util.Set;

public class A {
    // Static set to track which classes have already been instantiated
    private static final Set<Class<?>> INSTANTIATED_CLASSES = new HashSet<>();

    public A() {
        Class<?> currentClass = this.getClass();
        
        // Synchronize to prevent race conditions in multi-threaded environments
        synchronized (INSTANTIATED_CLASSES) {
            if (INSTANTIATED_CLASSES.contains(currentClass)) {
                throw new IllegalStateException(
                    "Cannot create more than one instance of " + currentClass.getName()
                );
            }
            INSTANTIATED_CLASSES.add(currentClass);
        }
    }
}

A subclass (like E) requires no extra code—its constructor will automatically inherit the parent class's instantiation check:

public class E extends A {
    // No additional logic needed; parent constructor handles the singleton check
}

And here's the test main method matching your example:

public class Main {
    public static void main(String[] args) {
        try {
            A obj1 = new A(); // Creates instance successfully
            System.out.println("Created instance of A");
            A obj2 = new A(); // Throws exception
        } catch (IllegalStateException e) {
            System.out.println(e.getMessage());
        }

        try {
            E obj3 = new E(); // Creates instance successfully
            System.out.println("Created instance of E");
            E obj4 = new E(); // Throws exception
        } catch (IllegalStateException e) {
            System.out.println(e.getMessage());
        }
    }
}

Key Explanations

  • Static Class Tracking: The INSTANTIATED_CLASSES set stores the Class object of each type that's been instantiated. Since each class has a unique Class instance, this ensures we track every subclass and the base class individually.
  • Constructor Enforcement: The check happens directly in the base class constructor. Every subclass (whether using the default constructor or a custom one) must call the parent constructor (either explicitly with super() or implicitly), so the validation logic applies to all subclasses automatically.
  • Thread Safety: The synchronized block around the set operations prevents race conditions where multiple threads might try to instantiate the same class at the same time, bypassing the check.
  • Exception Type: IllegalStateException is the right choice here because attempting to create a second instance violates the intended state of the class.

Edge Cases to Consider

  • Custom Subclass Constructors: Even if a subclass defines its own constructor (with parameters), as long as it calls super() (which it must, either explicitly or implicitly), the singleton check will still work. For example:
    public class B extends A {
        public B(String value) {
            super(); // Triggers the instantiation check
            // Subclass-specific logic here
        }
    }
    
  • Reflection Protection: This implementation even blocks reflection-based duplicate instantiation. If someone uses reflection to call the constructor a second time, the check in the constructor will still trigger and throw an exception.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:47:04