【问题标题】:Invoke static initializer again再次调用静态初始化器
【发布时间】:2010-10-15 12:44:17
【问题描述】:

一旦一个类被加载,有没有办法再次调用静态初始化器?

public class Foo {

    static {
        System.out.println("bar");
    }

}

编辑:

我需要调用静态初始化器,因为我没有编写原始类,而我需要调用的逻辑是在静态初始化器中实现的。

【问题讨论】:

    标签: java static static-initializer


    【解决方案1】:

    将初始化代码放在单独的公共静态方法中,以便您可以从静态初始化程序和其他地方调用它?

    【讨论】:

    • 我无法修改代码。它在第三方库中,我不打算使用常规静态方法中的代码创建自己的分发。 :) 我使用的解决方案是将代码复制并粘贴到另一个类中,这样它就可以使用常规的静态方法。但我不喜欢它。干燥
    • 嗯...那么我的下一个问题是,为什么第 3 方类在静态初始化程序中有您可能想要重新调用的逻辑?!
    • 它将在静态初始化器上加载和处理一个 XML 配置文件,我想重新加载 xml。
    • 静态初始化器有 70 + LOC。
    • 呃……你有我的同情心! :)
    【解决方案2】:

    如果类由不同的 ClassLoader 多次加载,则逻辑会多次运行的一种情况。请注意,在这种情况下,它们本质上是不同的类。

    不过,一般来说,这些都是一次性交易。如果您希望能够多次调用逻辑,请按照其他人的建议进行操作并将其放入静态方法中。

    【讨论】:

    • 我试图找到有关类加载器的参考,但找不到好的参考。你有吗?
    • 唉,不。我的知识来自 VM 规范、javadoc、服务器手册和各种互联网资源。你可以比谷歌搜索“developerWorks”和“ClassLoader”做得更糟。
    • 这里的答案有一个小的类加载器示例:stackoverflow.com/questions/33040829/…
    【解决方案3】:

    我同意 Earwicker 的回答。只需将静态初始化提取到单独的静态方法即可。

    public class Foo {
    
        static {
            Foo.initialize();
        }
    
        public static void initialize() {
            System.out.println("bar");
        }
    
    }
    

    【讨论】:

    • 为什么投反对票?否决我的人可以解释原因吗?
    【解决方案4】:

    如果您真的想要确切问题的确切答案,答案是否定的。无法通过反射调用静态初始化程序或 instanceInitializer。

    文档清楚地说:

    对于getDeclaredMethod(String name)

    如果名称是“”或“”,则会引发 NoSuchMethodException。

    对于getDeclaredMethods()

    返回的数组中不包含类初始化方法。

    所以不,即使通过反射也不可能调用它。

    【讨论】:

      【解决方案5】:

      您可以尝试扩展包含静态代码的类,然后放入您自己的静态初始化程序。不太确定它是否有效,但是:

      public class OldBadLibraryClass {
         static {
            System.out.println("oldBadLibrary static init");
         }
      }
      
      //next file
      
      public class MyBetterClass extends OldBadLibraryClass {
         static {
            System.out.println("MyBetterClass init");
         }
      }
      
      
      public class Test {
         public static void main(String[] args) {
            new MyBetterClass();
         }
      }
      

      看看上面的打印是否按照你期望的顺序。在我的机器上,它工作。

      虽然这完全是一个 hack,而且非常脆弱。将旧类修改为具有可以覆盖的 init() 方法确实会好得多。

      【讨论】:

        【解决方案6】:

        https://stackoverflow.com/a/19302726/2300018 是我的帖子,我在其中重新加载了一个实用程序类以重新运行静态初始化程序以进行单元测试。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-28
          • 1970-01-01
          • 2014-10-06
          • 1970-01-01
          • 2011-04-24
          • 2011-02-06
          相关资源
          最近更新 更多