Scala

Scala case class 动态copy

2019-08-25  本文已影响0人  大猪大猪

在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"))
上一篇下一篇

猜你喜欢

热点阅读