错误记录Kotlin 代码编译时报错 ( Variable ‘name‘ must be initialized | 初始化块定义在所有属性之后 )

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了错误记录Kotlin 代码编译时报错 ( Variable ‘name‘ must be initialized | 初始化块定义在所有属性之后 )相关的知识,希望对你有一定的参考价值。

文章目录





一、报错信息



在 Kotlin 中 , init 初始化块 要 定义在所有成员属性之后 ;

如果在 init 初始化块 中 , 使用到了 成员属性 , 有可能出现 编译时报错信息 ;


报错代码示例 :

class Hello
    init 
        val name1 = name.capitalize()
    
    var name = "Tom"

报错信息 :

Variable 'name' must be initialized





二、问题分析



双击 Shift , 选择 " Show Kotlin Bytecode " 选项 ,


在 " Kotlin Bytecode " 界面查看 Kotlin 编译后的 字节码数据 , 点击 " Decompile " 按钮 , 将字节码反编译回 Java 代码 ;

完整的 反编译 后的 Java 代码如下 :

// HelloKt.java
import kotlin.Metadata;

@Metadata(
   mv = 1, 4, 2,
   bv = 1, 0, 3,
   k = 2,
   d1 = "\\u0000\\b\\n\\u0000\\n\\u0002\\u0010\\u0002\\n\\u0000\\u001a\\u0006\\u0010\\u0000\\u001a\\u00020\\u0001¨\\u0006\\u0002",
   d2 = "main", "", "KotlinDemo"
)
public final class HelloKt 
   public static final void main() 
   

   // $FF: synthetic method
   public static void main(String[] var0) 
      main();
   

// Hello.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = 1, 4, 2,
   bv = 1, 0, 3,
   k = 1,
   d1 = "\\u0000\\u0014\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0002\\b\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0005\\u0018\\u00002\\u00020\\u0001B\\u0005¢\\u0006\\u0002\\u0010\\u0002R\\u001a\\u0010\\u0003\\u001a\\u00020\\u0004X\\u0086\\u000e¢\\u0006\\u000e\\n\\u0000\\u001a\\u0004\\b\\u0005\\u0010\\u0006\\"\\u0004\\b\\u0007\\u0010\\b¨\\u0006\\t",
   d2 = "LHello;", "", "()V", "name", "", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "KotlinDemo"
)
public final class Hello 
   @NotNull
   private String name;

   @NotNull
   public final String getName() 
      return this.name;
   

   public final void setName(@NotNull String var1) 
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   

   public Hello() 
      String var1 = StringsKt.capitalize(this.name);
      this.name = "Tom";
   

其中在 构造函数中的代码 :

   public Hello() 
      String var1 = StringsKt.capitalize(this.name);
      this.name = "Tom";
   

这里先调用 name 属性 , 然后再为 name 属性赋值 ; 这是错误的根本原因 ;





三、解决方案 ( 初始化块定义在所有属性之后 )



将属性定义在 初始化块 之前 ;

代码示例 :

class Hello
    var name = "Tom"
    init 
        val name1 = name.capitalize()
    

此时代码的编译时报错消失 ;


双击 Shift , 选择 " Show Kotlin Bytecode " 选项 ,


在 " Kotlin Bytecode " 界面查看 Kotlin 编译后的 字节码数据 , 点击 " Decompile " 按钮 , 将字节码反编译回 Java 代码 ;

再次查看反编译后的 java 代码 :

// HelloKt.java
import kotlin.Metadata;

@Metadata(
   mv = 1, 4, 2,
   bv = 1, 0, 3,
   k = 2,
   d1 = "\\u0000\\b\\n\\u0000\\n\\u0002\\u0010\\u0002\\n\\u0000\\u001a\\u0006\\u0010\\u0000\\u001a\\u00020\\u0001¨\\u0006\\u0002",
   d2 = "main", "", "KotlinDemo"
)
public final class HelloKt 
   public static final void main() 
   

   // $FF: synthetic method
   public static void main(String[] var0) 
      main();
   

// Hello.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = 1, 4, 2,
   bv = 1, 0, 3,
   k = 1,
   d1 = "\\u0000\\u0014\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0002\\b\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0005\\u0018\\u00002\\u00020\\u0001B\\u0005¢\\u0006\\u0002\\u0010\\u0002R\\u001a\\u0010\\u0003\\u001a\\u00020\\u0004X\\u0086\\u000e¢\\u0006\\u000e\\n\\u0000\\u001a\\u0004\\b\\u0005\\u0010\\u0006\\"\\u0004\\b\\u0007\\u0010\\b¨\\u0006\\t",
   d2 = "LHello;", "", "()V", "name", "", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "KotlinDemo"
)
public final class Hello 
   @NotNull
   private String name = "Tom";

   @NotNull
   public final String getName() 
      return this.name;
   

   public final void setName(@NotNull String var1) 
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   

   public Hello() 
      String var1 = StringsKt.capitalize(this.name);
   

关注 Hello 类的代码 , 在代码中 , 先为 name 赋值 , 然后在 构造函数中调用 name 属性 ;

public final class Hello 
   @NotNull
   private String name = "Tom";

   @NotNull
   public final String getName() 
      return this.name;
   

   public final void setName(@NotNull String var1) 
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   

   public Hello() 
      String var1 = StringsKt.capitalize(this.name);
   

以上是关于错误记录Kotlin 代码编译时报错 ( Variable ‘name‘ must be initialized | 初始化块定义在所有属性之后 )的主要内容,如果未能解决你的问题,请参考以下文章

错误记录Kotlin 代码运行时报错 ( 在 init 初始化块中调用还未初始化的成员属性 )

错误记录Kotlin 代码运行时报错 ( 在 init 初始化块中调用还未初始化的成员属性 )

错误记录Android Studio 编译时 Kotlin 代码编译报错 ( Not enough information to infer type variable T )

错误记录Kotlin 代码运行时报错 ( 成员属性初始化顺序是按照从上到下顺序进行的 , 上面的属性不要调用下面未进行初始化的属性 )

错误记录Kotlin 代码运行时报错 ( 成员属性初始化顺序是按照从上到下顺序进行的 , 上面的属性不要调用下面未进行初始化的属性 )

错误记录Android Studio 编译时 Kotlin 代码编译报错 ( 升级支持库时处理 @NonNull 参数 )