Field visibility in Data class when decompiled to Java code

From documentation, by default every field is Public but when I decompile a data class into java code, it shows fields marked as Private final. What’s going on here?

Example data class

data class A (
        val nickname: String,
         var name: String

)

Decompiled bytecode

public final class A {
   @NotNull
   private final String nickname;
   @NotNull
   private String name;

   @NotNull
   public final String getNickname() {
      return this.nickname;
   }

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

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

   public A(@NotNull String nickname, @NotNull String name) {
      Intrinsics.checkParameterIsNotNull(nickname, "nickname");
      Intrinsics.checkParameterIsNotNull(name, "name");
      super();
      this.nickname = nickname;
      this.name = name;
   }

   @NotNull
   public final String component1() {
      return this.nickname;
   }

   @NotNull
   public final String component2() {
      return this.name;
   }

   @NotNull
   public final A copy(@NotNull String nickname, @NotNull String name) {
      Intrinsics.checkParameterIsNotNull(nickname, "nickname");
      Intrinsics.checkParameterIsNotNull(name, "name");
      return new A(nickname, name);
   }

   // $FF: synthetic method
   // $FF: bridge method
   @NotNull
   public static A copy$default(A var0, String var1, String var2, int var3, Object var4) {
      if((var3 & 1) != 0) {
         var1 = var0.nickname;
      }

      if((var3 & 2) != 0) {
         var2 = var0.name;
      }

      return var0.copy(var1, var2);
   }

   public String toString() {
      return "A(nickname=" + this.nickname + ", name=" + this.name + ")";
   }

   public int hashCode() {
      return (this.nickname != null?this.nickname.hashCode():0) * 31 + (this.name != null?this.name.hashCode():0);
   }

   public boolean equals(Object var1) {
      if(this != var1) {
         if(var1 instanceof A) {
            A var2 = (A)var1;
            if(Intrinsics.areEqual(this.nickname, var2.nickname) && Intrinsics.areEqual(this.name, var2.name)) {
               return true;
            }
         }

         return false;
      } else {
         return true;
      }
   }
}

Kotlin has properties, which on the JVM are represented as private fields with generated get and set methods.

1 Like

I don’t see where your problem is, but I will try to explain this anyway.
Your fields are publicly accessible, meaning from Kotlin code you can do this:

val a = A("Jace", "Jonathan Christopher")
println(a.nickname)
println(a.name)
a.name = "Sebastian")
println(a.name)

In Java as you point out the fields are private or private final. In Java the convention is to have all fields private and if they are supposed to be accessed from outside the class create a public getter and setter (The getName, setName, getNickname methods).
If you use Java Code from within Kotlin, all getters and setters are automatically mapped to Kotlin properties.

Final in Java means, the same as val in Kotlin. It describes a field that can not be reassigned.
In Java final can also be used on methods meaning the method can not be overridden (In Kotlin all methods are “final” by default and you need to use open if you don’t want them to be).

1 Like

Thanks Sxtanna. It helped :slight_smile: