Scala case class 动态copy

在scala中、case class 确实好用、但是只支持指定字段名称使用copy复制、在动态情场中、一个类的字段可是非常多的、如何处理这样的问题?这就得使用到反射功能了、下面已经给大家写好了。

CopyUtil.scala

import java.lang.reflect.Modifier

object CopyUtil {

  def copy[T](o: T, vals: (String, Any)*): T = {
    if(vals.isEmpty) return o
    val copier = new Copier(o.getClass)
    val maps = vals.map(kv => {
      kv._1 -> kv._2
    }).toMap
    copier(o, maps)
  }

  def copy[T](o: T, vals: Map[String, Any]): T = {
    if(vals.isEmpty) return o
    val copier = new Copier(o.getClass)
    copier(o, vals)
  }

  private class Copier(cls: Class[_]) {
    private val ctor = cls.getConstructors.apply(0)
    private val getters = cls.getDeclaredFields
      .filter {
        f =>
          val m = f.getModifiers
          Modifier.isPrivate(m) && Modifier.isFinal(m) && !Modifier.isStatic(m)
      }
      .take(ctor.getParameterTypes.length)
      .map(f => cls.getMethod(f.getName))

    def apply[T](o: T, vals: Map[String, Any]): T = {
      val byIx = vals.map {
        case (name, value) =>
          val ix = getters.indexWhere(_.getName == name)
          if (ix < 0) throw new IllegalArgumentException("Unknown field: " + name)
          (ix, value.asInstanceOf[Object])
      }.toMap

      val args = getters.indices.map {
        i =>
          byIx.getOrElse(i, getters(i).invoke(o))
      }
      ctor.newInstance(args: _*).asInstanceOf[T]
    }

  }

}

使用

case class User(username:String,password:String)
val user = User("lake","admin")
CopyUtil.copy(user,Map("username"->"admin"))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值