在 'hashCode()' 中访问了非值字段

Non-value field is accessed in 'hashCode()'

它发生在 id 上。 (在 'hashCode()' 中访问非值字段)

我该如何解决?

这是我的代码:

import java.util.Date

case class Category() {
    var id: Integer = _
    var parentId: Integer = _
    var name: String = _
    var status: Boolean = _
    var sortOrder: Integer = _
    var createTime: Date = _
    var updateTime: Date = _

    def this(id: Integer, parentId: Integer, name: String, status: Boolean, sortOrder: Integer, createTime: Date, updateTime: Date) {
        this()
        this.id = id
        this.parentId = parentId
        this.name = name
        this.status = status
        this.sortOrder = sortOrder
        this.createTime = createTime
        this.updateTime = updateTime
    }

    override def hashCode(): Int = {
        if (id != null) id.hashCode() else 0
    }
}

如果我把var id改成val id就可以了。但是我需要setter,我不能把它设置成val.

hashCode 中的非值字段意味着您正在依赖可变字段生成 classes 哈希码,这可能很危险,具体取决于您如何使用 class。例如,假设您有一个 HashMap[Category, String],您在哈希映射中放置了一个条目,并且它们改变了 id 字段,现在哈希映射无法再通过它的哈希码找到 class 实例。

您将案例 class 视为常规的可变 Java class。 Case classes 提供了以语法方便的方式封装 immutable 数据的机制(您还可以免费获得一些不错的东西,例如 hashCodeequals, 等等)。你可以做的是让你的案例 class 通过它的主要构造函数接受参数:

case class Category(id: Int,
                    parentId: Int,
                    name: String,
                    status: Boolean,
                    sortOrder: Int,
                    createTime: Date,
                    updateTime: Date) {
  override def hashCode(): Int = id.hashCode()
}

如果要更新 Category,可以使用在案例 class:

上定义的实用程序 copy 方法
val cat = Category(id = 1,
                   parentId = 1,
                   name = "Hello",
                   status = true,
                   sortOrder = 1,
                   createTime = new Date(123132123L),
                   updateTime = new Date(52234234L))

val newCat: Category = cat.copy(id = 2)

解决此问题的另一种方法(我不太喜欢 TBH)是将所有字段设置为 Option[T],并将默认值设置为 None:

case class Category(id: Option[Int] = None,
                    parentId: Option[Int] = None,
                    name: Option[String] = None,
                    status: Option[Boolean] = None,
                    sortOrder: Option[Int] = None,
                    createTime: Option[Date] = None,
                    updateTime: Option[Date] = None) {
  override def hashCode(): Int = id.map(_.hashCode()).getOrElse(0)
}

然后在可以用数据填充 class 后更新它们:

val cat = Category()
val newCat = cat.copy(id = Some(1))

经过多次尝试,我觉得这应该是个不错的选择。 有任何想法吗?

override def hashCode(): Int = {
    if (getId != null) getId.hashCode() else 0
}