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"))