如何确保无法使用反射从 class 外部创建具有私有构造函数的 class 实例?

How to make sure instance of a class with a private constructor can not be created from outside of the class using Reflection?

我知道可以使用反射创建具有私有构造函数的 class 实例,但是有什么方法可以确保 class 的实例只能在相同 class 使用自己的私有构造函数?

让我们举一个带有私有构造函数的 class 测试的例子。

import java.lang.reflect.Constructor;

   import java.lang.reflect.InvocationTargetException;

   class Test   
   {

      private Test()  //private constructor
      {
      } 
   }

  public class Sample{

      public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
     {

       Class c=Class.forName("Test"); //specify class name in quotes

       //----Accessing private constructor
       Constructor con=c.getDeclaredConstructor();
       con.setAccessible(true);     
       Object obj=con.newInstance();
   }   
} 

我的问题是 - 有什么方法可以确保 class 的实例只能在同一个 class 中创建,而不是使用反射或任何其他方法从外部创建?

您在评论中提到的一种方法是使用 Exception,另一种方法是使用 Thread.currentThread()

 package app.test;
    public class Test19 {
    ..
        private Test19() {
    
            if (Thread.currentThread().getStackTrace()[1].getClassName() == "app.test.Test19") {
                // initialize member fields etc.
            } else {
                throw new IllegalAccessException();
            }
        }
     }
    

有多种方法可以防止创建 - 但很难判断哪一种适合您的 use-case:

  1. 在构造函数中抛出异常

    您可以无条件地抛出异常 - 使其(几乎)无法实例化实例 - 或者仅在特定条件下抛出。

    一些条件可以是:

  2. 使用 Java 个模块。

    由于其他模块无法深入反映到其他命名模块中,Constructor.setAccessible 将无法在您自己的模块之外的 class 上工作。
    当然,此限制不适用于您自己的模块 - 但您应该能够控制自己的模块 ;)。

  3. 安装一个SecurityManager.

    阻止 Constructor.setAccessible 成功返回。
    但是安全管理器已被弃用,因此我不推荐使用它。

注意:大多数解决方案都可以通过某种方式规避。有时可以添加额外的防御措施。但到头来,就成了猫捉老鼠的游戏。