Java 什么是;T是顶级类,执行嵌套在T中的assert语句;什么意思?
我正在学习“类和接口的初始化”,它说“T是一个顶级类,执行嵌套在T中的assert语句。” 有谁能告诉我什么是“T是顶级类,并且执行嵌套在T中的assert语句”是指一个示例 这句话来自,原文如下: 类或接口类型T将在第一次出现以下任一情况之前立即初始化:Java 什么是;T是顶级类,执行嵌套在T中的assert语句;什么意思?,java,Java,我正在学习“类和接口的初始化”,它说“T是一个顶级类,执行嵌套在T中的assert语句。” 有谁能告诉我什么是“T是顶级类,并且执行嵌套在T中的assert语句”是指一个示例 这句话来自,原文如下: 类或接口类型T将在第一次出现以下任一情况之前立即初始化: T是一个类,并且创建了T的一个实例 T是一个类,调用由T声明的静态方法 分配了一个由T声明的静态字段 使用T声明的静态字段,该字段不是常量变量(§4.12.4) T是一个顶级类,执行嵌套在T中的assert语句(§14.10) 我可以对此
- T是一个类,并且创建了T的一个实例
- T是一个类,调用由T声明的静态方法
- 分配了一个由T声明的静态字段
- 使用T声明的静态字段,该字段不是常量变量(§4.12.4)
- T是一个顶级类,执行嵌套在T中的assert语句(§14.10)
我可以对此作部分解释。它指的是启用/禁用断言。断言由
-ea
vm参数启用
assert
的一个要点是:
启用在其类完成初始化之前执行的assert语句
假设未给出-ea
,您运行以下代码:
public class Q1 {
public static void main(String[] args) {
Bar b = new Bar();
}
}
class Bar {
static {
boolean enabled = false;
assert enabled = false; //line(a)
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
System.out.println("as");
Baz.testAsserts();
}
}
class Baz extends Bar {
static void testAsserts() {
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
}
}
在上面的例子中,当b
被初始化时,Java保证在调用行(a)
之前,断言被禁用(即,行(a)根本不被执行)。因为assert enable/disable是类初始化的一部分,所以在所示的语句中提到了它
之所以提到顶级类而不是其他所有类,原因是这样的。更详细的行为如下:
public class Q1 {
public static void main(String[] args) {
Baz.testAsserts();
// Will execute after Baz is initialized.
}
}
class Bar {
static {
Baz.testAsserts();
// Will execute before Baz is initialized!
}
}
class Baz extends Bar {
static void testAsserts() {
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
}
}
即使未使用-ea
标志,它仍会抛出一个断言异常
。发生的情况如下:
条形图
尚未完全初始化,因此在此阶段为true
Bar
调用Baz.testAsserts()
。断言仍然处于启用状态(请记住,禁用断言与类初始化有关,而Bar仍然没有完全初始化)。现在Baz.testAsserts()抛出AssertionException
assert
之前,它将禁用/启用它(无论给出什么vm参数)。但是如果它不是顶级类,那么行为取决于顶级类的初始化。要解释这一点,请参见以下内容:
class Bar {
static {
//Baz.testAsserts();
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
// Will execute before Baz is initialized!
}
}
class Baz extends Bar {
static void testAsserts() {
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
}
}
当
栏
初始化良好时,这将打印断言禁用
断言禁用<代码>栏初始化禁用类的断言
,因此对于Baz
这是一个顶级类:
class TopLevel {
...
}
这是一个断言语句:
assert( condition );
其中,条件
是一些布尔表达式
如果A出现在B定义的花括号内,则A在词汇上嵌套在B中。例如,字段、方法、静态块按词汇嵌套在类定义中。语句在词汇上嵌套在方法或静态块中。局部定义嵌套在方法或块中,这些方法或块本身嵌套在方法中
因此,词汇嵌套在顶级类中的assert语句可以是:
class A {
static {
assert ( 2+2 == 4 );
}
}
我知道该如何阅读该规范,但OpenJDK1.7.0_40的行为与所述不符,Oracle JDK1.7.0_25也不一样 顶级类是不嵌套在任何其他类中的类。断言语句可以出现在可执行代码中,即方法、构造函数或静态初始值设定项块中。这些情况中的大多数是由其他项目处理的:静态方法已经包括在内,其他方法以及构造函数属于所述类的对象的创建范围,静态初始值设定项块是初始化过程的一部分,它是任何其他事件的结果 因此,我能想到的唯一方法是通过嵌套类来创建一个词汇嵌套语句,而不触发这些情况。例如,类似这样的事情:
class Outer {
static {
System.out.println("Outer initialized");
}
static class Nested {
static void foo() {
assert System.out == null;
}
}
}
但是如果我在启用断言的情况下运行Outer.Nested.foo()
,那么我会得到断言错误(因此语句被执行),但不会得到Outer initialized
消息。因此,即使执行了词汇嵌套的assert语句,顶级类也没有初始化
要么我误解了这里的规范,要么提到的实现没有遵循它
至于基本原理:我认为这个需求的要点是,启用和禁用断言是通过类的隐藏静态(和iirc.final)字段实现的。因此,当执行assert语句时,它必须检查该字段,因此必须初始化该字段,因此必须初始化该类。但在上述代码中,相关字段可能是Outer.Nested
的字段,而不是Outer
本身的字段。因此,Outer
不必在该点初始化是有道理的。但是除了上面的构造,我想不出最后一条规则适用,而其他规则都不适用的情况。您已链接到
在java bug中,有一条注释解释说列表的最后一个项目符号“T是顶级类,并且执行了按词汇嵌套在T中的assert语句(§14.10)”,这完全是错误的,它在版本6中被错误地插入到JLS中,并一直保留到版本7,因为没有人注意到它
我发现