The board field in the PuzzleBoard class is an IntArray, when compiled it is turned into a primitive integer array. Individual array elements are never compared when checking the equality of primitive integer arrays. So calling equals on int array returns false as they are pointing to different objects. Eventually, this results in getting false in the equals() method, even though array elements are the same.
Byte code check
Looking at the decompiled java byte code, the Kotlin compiler generates some functions of data classes for us.
This includes,
- copy()function
- toString()function - takes form- ClassName(var1=val1, var2=val2, ...)
- hashCode()function
- equals()function
Hash code is generated by adding the hash code of individual variables and multiplying by 31. The reason for multiplying is that it can be replaced with the bitwise operator and according to experimental results, 31 and other numbers like 33, 37, 39, 41, etc. gave fever clashes when multiplied.
Take a look at decompiled java byte code of the Kotlin class PuzzleBoard which reveals the secrets of data classes.
@Metadata(
   mv = {1, 7, 1},
   k = 1,
   d1 = {"\u0000(\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u0015\n\u0002\b\u0004\n\u0002\u0010\b\n\u0002\b\u0007\n\u0002\u0010\u000b\n\u0002\b\u0003\n\u0002\u0010\u000e\n\u0000\b\u0086\b\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\t\u0010\r\u001a\u00020\u0003HÆ\u0003J\u0013\u0010\u000e\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u0003HÆ\u0001J\u0013\u0010\u000f\u001a\u00020\u00102\b\u0010\u0011\u001a\u0004\u0018\u00010\u0001HÖ\u0003J\t\u0010\u0012\u001a\u00020\bHÖ\u0001J\t\u0010\u0013\u001a\u00020\u0014HÖ\u0001R\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006R\u001b\u0010\u0007\u001a\u00020\b8FX\u0086\u0084\u0002¢\u0006\f\n\u0004\b\u000b\u0010\f\u001a\u0004\b\t\u0010\n¨\u0006\u0015"},
   d2 = {"Lcom/aureusapps/androidpagingbasics/data/PuzzleBoard;", "", "board", "", "([I)V", "getBoard", "()[I", "dimension", "", "getDimension", "()I", "dimension$delegate", "Lkotlin/Lazy;", "component1", "copy", "equals", "", "other", "hashCode", "toString", "", "androidpagingbasics_debug"}
)
public final class PuzzleBoard {
   @NotNull
   private final Lazy dimension$delegate;
   @NotNull
   private final int[] board;
   public final int getDimension() {
      Lazy var1 = this.dimension$delegate;
      Object var3 = null;
      return ((Number)var1.getValue()).intValue();
   }
   @NotNull
   public final int[] getBoard() {
      return this.board;
   }
   public PuzzleBoard(@NotNull int[] board) {
      Intrinsics.checkNotNullParameter(board, "board");
      super();
      this.board = board;
      this.dimension$delegate = LazyKt.lazy((Function0)(new Function0() {
         // $FF: synthetic method
         // $FF: bridge method
         public Object invoke() {
            return this.invoke();
         }
         public final int invoke() {
            return (int)Math.sqrt((double)PuzzleBoard.this.getBoard().length);
         }
      }));
   }
   @NotNull
   public final int[] component1() {
      return this.board;
   }
   @NotNull
   public final PuzzleBoard copy(@NotNull int[] board) {
      Intrinsics.checkNotNullParameter(board, "board");
      return new PuzzleBoard(board);
   }
   // $FF: synthetic method
   public static PuzzleBoard copy$default(PuzzleBoard var0, int[] var1, int var2, Object var3) {
      if ((var2 & 1) != 0) {
         var1 = var0.board;
      }
      return var0.copy(var1);
   }
   @NotNull
   public String toString() {
      return "PuzzleBoard(board=" + Arrays.toString(this.board) + ")";
   }
   public int hashCode() {
      int[] var10000 = this.board;
      return var10000 != null ? Arrays.hashCode(var10000) : 0;
   }
   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof PuzzleBoard) {
            PuzzleBoard var2 = (PuzzleBoard)var1;
            if (Intrinsics.areEqual(this.board, var2.board)) {
               return true;
            }
         }
         return false;
      } else {
         return true;
      }
   }
}