如果静态变量处于RIWO(只读间接写入)状态。静态变量不能直接访问。
这是代码
Sub Document_Open()
Dim sNumber As String, mNumber As String, iDate As String, i As Integer
Dim varData(1 To 3) As String
varData(1) = "SerialNumber"
varData(2) = "ModelNumber"
varData(3) = "IssueDate"
Dim varInput(1 To 3) As String
varInput(1) = InputBox("Please enter the Serial Number", "Serial number", "Enter the Serial Number here")
varInput(2) = InputBox("Please enter the Model Number", "Model number", "Enter the Model Number here")
varInput(3) = InputBox("Please enter the Date of Issue, dd.mm.yyyy", "Date of Issue", "Enter the Date of Issue here")
For i = 1 To 3
With ActiveDocument
If DocVarExists(varData(i), ActiveDocument) Then
.Variables(varData(i)).Value = varInput(i)
Else
.Variables.Add Name:=varData(i), Value:=varInput(i)
End If
.Fields.Update
End With
Next i
End Sub
Function DocVarExists(sVarName As String, doc As Word.Document) As Boolean
Dim var As Word.Variable, bExists As Boolean
bExists = False
For Each var In doc.Variables
If var.Name = sVarName Then
bExists = True
Exit For
End If
Next
DocVarExists = bExists
End Function
在这种情况下,将出现非法的前向参考编译时间错误。
但是如果您使用类名访问静态变量,则可以对其进行访问。
这是代码示例
class Test {
static{
System.out.println(x);
}
static int x = 10;
public static void main(String[] args) {
}
}
答案是:0
这怎么可能?这不是直接访问吗?
答案 0 :(得分:1)
根据JLS 12.4.1. When Initialization Occurs和this answer:
类的静态初始化通常在以下事件之一首次发生之前立即发生:
- 已创建该类的实例
- 该类的静态方法被调用
- 分配了该类的静态字段
- 使用了非恒定静态字段
在您的情况下,Test.x
的读数属于第4点(非恒定静态字段)。您的代码读取并输出0
,这是默认的int
值,但是您可以通过将字段final
标记为
static {
System.out.println(Test.x);
}
final static int x = 10;
代码现在将输出10
。您可以通过比较javap -c Test.class
的输出(非最终形式和最终形式)来查看它,字节码的顺序将在以下位置反转:
6: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
9: bipush 10
在我看来,Java编译器的前向引用错误是JVM静态初始化中陷阱的解决方法。
答案 1 :(得分:0)
这可能是Java编译器错误。
在您的第一种情况下,编译器成功找出了错误的用法。
以文本顺序执行类的类变量初始化器和静态初始化器,或者接口的字段初始化器,就像它们是单个块一样。
在声明变量之前,当然应禁止使用该变量。
不幸的是,在第二种情况下,编译器没有发现错误的用法。
以下事情会逐步发生:
Test
类,现在Test.class
对象是可访问的Test
类静态的初始化Test.x
。由于它不是常数,因此jvm转到METASPACE以获取该值。 int
默认为0。这样就可以打印出0
。x = 10
,将数据设置为METASPACE 顺便说一句,卡罗尔的答案有点错误。仅添加final
是不够的,另一个必要条件是它确实是常数。以下代码仍将打印0
。
static {
System.out.println(JustTest.x);
}
static final int x = Integer.valueOf(1);