这已经在您的跟踪中报告,作为
KT-16681
“Kotlin允许改变只读属性的字段”。
正如您在KT-16681中的回复中看到的,自定义getter被编译成另一个函数,这使得字段
foo
方法
getFoo()
变成两件无关的事情。
同样,从KT-16681中的回复中,这种违反(通过支持字段重新分配只读属性)将产生自Kotlin 1.3以来的错误。
更新:
在评论中,最初的海报提到
KT-16681
与此问题不同。然而,从这个问题中,我们可以看到Kotlin字节码
Tools -> Kotlin -> Show Kotlin Bytecode
(删除的元数据等):
public final class Test53699029Kt {
// access flags 0xA
private static I counter
// access flags 0x19
public final static getCounter()I
L0
LINENUMBER 3 L0
GETSTATIC Test53699029Kt.counter : I
IRETURN
L1
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x19
public final static setCounter(I)V
L0
LINENUMBER 3 L0
ILOAD 0
PUTSTATIC Test53699029Kt.counter : I
RETURN
L1
LOCALVARIABLE <set-?> I L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x19
public final static getFoo()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 7 L0
GETSTATIC Test53699029Kt.counter : I
DUP
ISTORE 0
ICONST_1
IADD
PUTSTATIC Test53699029Kt.counter : I
L1
LINENUMBER 8 L1
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
LDC "val"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
GETSTATIC Test53699029Kt.counter : I
INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ARETURN
L2
MAXSTACK = 2
MAXLOCALS = 1
// access flags 0x19
public final static main()V
L0
LINENUMBER 12 L0
INVOKESTATIC Test53699029Kt.getFoo ()Ljava/lang/String;
ASTORE 0
L1
LINENUMBER 13 L1
INVOKESTATIC Test53699029Kt.getFoo ()Ljava/lang/String;
ASTORE 1
L2
LINENUMBER 14 L2
INVOKESTATIC Test53699029Kt.getFoo ()Ljava/lang/String;
ASTORE 2
L3
LINENUMBER 15 L3
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
LDC "we got: "
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 0
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
BIPUSH 32
INVOKEVIRTUAL java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
BIPUSH 32
INVOKEVIRTUAL java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 3
L4
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 3
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
L5
L6
LINENUMBER 17 L6
RETURN
L7
LOCALVARIABLE c Ljava/lang/String; L3 L7 2
LOCALVARIABLE b Ljava/lang/String; L2 L7 1
LOCALVARIABLE a Ljava/lang/String; L1 L7 0
MAXSTACK = 2
MAXLOCALS = 4
// access flags 0x1009
public static synthetic main([Ljava/lang/String;)V
INVOKESTATIC Test53699029Kt.main ()V
RETURN
MAXSTACK = 0
MAXLOCALS = 1
正如我们所看到的,这里没有
福
只是一个
获取GET FULL()
,比较正常
val
宣言:
public final class Test53699029Kt {
// access flags 0xA
private static I counter
// access flags 0x19
public final static getCounter()I
L0
LINENUMBER 1 L0
GETSTATIC Test53699029Kt.counter : I
IRETURN
L1
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x19
public final static setCounter(I)V
L0
LINENUMBER 1 L0
ILOAD 0
PUTSTATIC Test53699029Kt.counter : I
RETURN
L1
LOCALVARIABLE <set-?> I L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1A
private final static Ljava/lang/String; foo = "aaa"
@Lorg/jetbrains/annotations/NotNull;() // invisible
// access flags 0x19
public final static getFoo()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 3 L0
GETSTATIC Test53699029Kt.foo : Ljava/lang/String;
ARETURN
L1
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x19
public final static main()V
L0
LINENUMBER 6 L0
GETSTATIC Test53699029Kt.foo : Ljava/lang/String;
ASTORE 0
L1
LINENUMBER 7 L1
GETSTATIC Test53699029Kt.foo : Ljava/lang/String;
ASTORE 1
L2
LINENUMBER 8 L2
GETSTATIC Test53699029Kt.foo : Ljava/lang/String;
ASTORE 2
L3
LINENUMBER 9 L3
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
LDC "we got: "
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 0
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
BIPUSH 32
INVOKEVIRTUAL java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
BIPUSH 32
INVOKEVIRTUAL java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 3
L4
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 3
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
L5
L6
LINENUMBER 11 L6
RETURN
L7
LOCALVARIABLE c Ljava/lang/String; L3 L7 2
LOCALVARIABLE b Ljava/lang/String; L2 L7 1
LOCALVARIABLE a Ljava/lang/String; L1 L7 0
MAXSTACK = 2
MAXLOCALS = 4
// access flags 0x1009
public static synthetic main([Ljava/lang/String;)V
INVOKESTATIC Test53699029Kt.main ()V
RETURN
MAXSTACK = 0
MAXLOCALS = 1
// access flags 0x8
static <clinit>()V
L0
LINENUMBER 3 L0
LDC "aaa"
PUTSTATIC Test53699029Kt.foo : Ljava/lang/String;
RETURN
MAXSTACK = 1
MAXLOCALS = 0
使用
val foo = "aaa"
会产生一个正常的
final static String foo
字段和
final static String getFoo()
方法,但使用
val foo: String
具有
get()
不会产生那个字段,只是产生一个方法。这个getter函数是由kotlin生成的,我相信字段的丢失是由于在声明中丢失了初始赋值
瓦尔
但是我找不到真正的文件
Getters and Setters in Kotlin
直接使用这个结论。
因此,这似乎是修改
final static
.
当不可变字段引用可变字段时,会出现问题。
瓦尔
不可重新分配,但它引用了
var
,一个可重新分配的字段,这导致修改
瓦尔
.