前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【错误记录】Kotlin 代码编译时报错 ( Variable ‘name‘ must be initialized | 初始化块定义在所有属性之后 )

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

作者头像
韩曙亮
发布2023-03-30 18:53:15
7740
发布2023-03-30 18:53:15
举报

文章目录

一、报错信息


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

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

报错代码示例 :

代码语言:javascript
复制
class Hello{
    init {
        val name1 = name.capitalize()
    }
    var name = "Tom"
}

报错信息 :

代码语言:javascript
复制
Variable 'name' must be initialized
在这里插入图片描述
在这里插入图片描述

二、问题分析


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

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

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

代码语言:javascript
复制
// 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";
   }
}

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

代码语言:javascript
复制
   public Hello() {
      String var1 = StringsKt.capitalize(this.name);
      this.name = "Tom";
   }

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

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


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

代码示例 :

代码语言:javascript
复制
class Hello{
    var name = "Tom"
    init {
        val name1 = name.capitalize()
    }
}

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

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

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

代码语言:javascript
复制
// 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 属性 ;

代码语言:javascript
复制
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);
   }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、报错信息
  • 二、问题分析
  • 三、解决方案 ( 初始化块定义在所有属性之后 )
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档