是否可以检查该类是否具有静态阻止(通过反射或其他方式)?

时间:2017-05-31 08:57:27

标签: java reflection static

是否可以检查该类是否有静态阻塞?

例如,要检查该类是否具有静态字段,可以通过调用clazz.getDeclaredFields()然后将其迭代到找到的静态字段来使用反射。

静态方法相同 - clazz.getDeclaredMethods()

getDeclaredMethods不会返回initclinit的方法。有没有其他方法可以检查该类是否有静态初始化块?

3 个答案:

答案 0 :(得分:3)

无法测试static初始值设定项的存在,因为该信息在字节码级别甚至不可用。在类文件中,可能存在单个初始化方法<clinit>,其存在可能是由static字段初始化器,static初始化块或仅存在的一个初始化块引起的。 assert语句在该类的某处,列举一些可能的原因。当然,可能有多个原因,包括此处未提及的原因。由于该字节码工件没有语言语义,因此没有反射方法来测试其存在。

但是,如果一个类没有可变的static字段,那么static初始值设定项就没有什么可以操作的,这可能会使“新鲜类”和类状态之间产生差异。 “新鲜”。虽然初始化程序可能有副作用,但如果没有要更改的static字段,则这些副作用不会改变类。但是如果初始化程序正在操纵其他类的状态,那么无论如何都会出现初始化顺序依赖性问题。

此外,由于满足某些标准而没有重新加载与该类交互的其他类而重新加载单个类的想法根本不起作用,因为这些旧类也将按原样保持链接,而不是使用新加载的类版本。

最简单的(如果不是唯一的)解决方案是重新加载特定类加载器的所有类,以获得一个全新的状态。尝试有选择地重新加载某些类只是一种优化尝试,但尝试优化测试环境没有意义......

答案 1 :(得分:1)

你无法做你想做的事,因为事情并非如此。即使你可能这是一个糟糕的主意,也意味着你的系统设计存在根本缺陷。

Static Initialization Blocks

  

静态初始化块是包含在其中的正常代码块   大括号,{},并以static关键字开头。这是一个例子:

print v.at(2) == 3
  

一个类可以有任意数量的静态初始化块,以及它们   可以出现在类体中的任何位置。运行时系统保证   静态初始化块按它们的顺序调用   出现在源代码中。

     

有静态块的替代方法 - 您可以编写私有块   静态方法:

static {
    // whatever code is needed for initialization goes here
}
  

私有静态方法的优点是可以重用它们   稍后如果你需要重新初始化类变量。

答案 2 :(得分:1)

使用以下代码。

 public static boolean check(Class<?> cls) {
    try {
        Method method = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer", Class.class);
        method.setAccessible(true);
        return (boolean) method.invoke(null, cls);
    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    }
    // trivial
    throw new RuntimeException();
}

static class Test { static { } }
static class Test2 { }

public static void main(String[] args) {
    assert check(Test.class);
    assert !check(Test2.class);
}