当静态变量处于RIWO状态时,可以直接访问它吗?

时间:2018-07-05 05:12:18

标签: java

如果静态变量处于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

这怎么可能?这不是直接访问吗?

2 个答案:

答案 0 :(得分:1)

根据JLS 12.4.1. When Initialization Occursthis 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编译器错误。

在您的第一种情况下,编译器成功找出了错误的用法。

  

以文本顺序执行类的类变量初始化器和静态初始化器,或者接口的字段初始化器,就像它们是单个块一样。

在声明变量之前,当然应禁止使用该变量。

不幸的是,在第二种情况下,编译器没有发现错误的用法。

以下事情会逐步发生:

  • JVM加载了Test类,现在Test.class对象是可访问的
  • 有人触发Test类静态的初始化
  • JVM按文本顺序运行,最前面的静态块将首先被调用
  • JVM尝试获取Test.x。由于它不是常数,因此jvm转到METASPACE以获取该值。 int默认为0。这样就可以打印出0
  • JVM运行下一行x = 10,将数据设置为METASPACE

顺便说一句,卡罗尔的答案有点错误。仅添加final是不够的,另一个必要条件是它确实是常数。以下代码仍将打印0

static {
  System.out.println(JustTest.x);
}

static final int x = Integer.valueOf(1);