Scala 2.11案例类的Java反射返回非声明字段?

时间:2015-11-09 23:48:53

标签: java scala reflection case-class

目前正在尝试使Java驱动程序与Scala案例类兼容。问题是反思失败了。

基本上,很多不需要的字段都会出现,并且会插入ANNOTATIONgetModifiers等字段。但是,当我使用调试器进行检查时,下面代码中的pojo确实是models.User。但是,在getClass()上调用pojo会产生java.lang.Class

我还尝试在案例类val中创建每个字段,然后在类上调用.getDeclaredFields(),但它具有相同的效果。

知道为什么会这样吗?这是Java代码:

private static Map<String, Object> toMap(Object pojo) {
    try {
        Map<String, Object> map = new HashMap<>();
        Class pojoClass = pojo.getClass();

        if (!Modifier.isPublic(pojoClass.getModifiers())) {
            throw new IllegalAccessException(String.format("%s's class should be public", pojo));
        }

        for (Field field : pojoClass.getDeclaredFields()) {
            System.out.println(field.toString());
        }

        for (Field field : pojoClass.getDeclaredFields()) {
            field.setAccessible(true);

            if (field.getDeclaringClass() == pojoClass) {
                Object value = field.get(pojo);

                if (value instanceof Integer) {
                    throw new IllegalAccessException(String.format(
                            "Make %s of %s Long instead of Integer", field.getName(), pojo));
                }

                map.put(field.getName(), value);
            }
        }

        return map;
    }
    catch (IllegalAccessException e) {
        throw new ReqlDriverError("Can't convert %s to a ReqlAst: %s", pojo, e.getMessage());
    }
}

以下是我的Scala案例类:

case class User(
  userId: String,
  loginInfo: LoginInfo,
  firstName: Option[String],
  lastName: Option[String],
  fullName: Option[String],
  email: Option[String],
  avatarURL: Option[String]) extends Identity

如果我遍历getDeclaredFields(),我会得到以下内容:

ANNOTATION
ENUM
SYNTHETIC
cachedConstructor
newInstanceCallerCache
name
allPermDomain
useCaches
reflectionData
classRedefinedCount
genericInfo
serialVersionUID
serialPersistentFields
reflectionFactory
initted
enumConstants
enumConstantDirectory
annotationData
annotationType
classValueMap

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

您列出了Class

的字段
scala> classOf[Class[_]].getDeclaredFields
res4: Array[java.lang.reflect.Field] = Array(private static final int java.lang.Class.ANNOTATION, private static final int java.lang.Class.ENUM, private static final int java.lang.Class.SYNTHETIC, private transient volatile java.lang.reflect.Constructor java.lang.Class.cachedConstructor, private transient volatile java.lang.Class java.lang.Class.newInstanceCallerCache, private transient java.lang.String java.lang.Class.name, private static java.security.ProtectionDomain java.lang.Class.allPermDomain, private static boolean java.lang.Class.useCaches, private transient volatile java.lang.ref.SoftReference java.lang.Class.reflectionData, private transient volatile int java.lang.Class.classRedefinedCount, private transient volatile sun.reflect.generics.repository.ClassRepository java.lang.C...

我不知道Identity是什么。

Scala的:

package ccreflect

case class User(
  userId: String,
  loginInfo: String,
  firstName: Option[String],
  lastName: Option[String],
  fullName: Option[String],
  email: Option[String],
  avatarURL: Option[String])

object Test extends App {
  Console println runtime.ScalaRunTime.stringOf(
    Util.toMap(User("Bob", "xxx", None, None, None, None, None))
  )
}

爪哇:

package ccreflect;

import java.util.Map;
import java.util.HashMap;
import java.lang.reflect.*;


public class Util {

public static Map<String, Object> toMap(Object pojo) {
    try {
        Map<String, Object> map = new HashMap<>();
        Class pojoClass = pojo.getClass();

        if (!Modifier.isPublic(pojoClass.getModifiers())) {
            throw new IllegalAccessException(String.format("%s's class should be public", pojo));
        }

        for (Field field : pojoClass.getDeclaredFields()) {
            System.out.println(field.toString());
        }

        for (Field field : pojoClass.getDeclaredFields()) {
            field.setAccessible(true);

            if (field.getDeclaringClass() == pojoClass) {
                Object value = field.get(pojo);

                if (value instanceof Integer) {
                    throw new IllegalAccessException(String.format(
                            "Make %s of %s Long instead of Integer", field.getName(), pojo));
                }

                map.put(field.getName(), value);
            }
        }

        return map;
    }
    catch (IllegalAccessException e) {
        throw new RuntimeException(String.format("Can't convert %s to a ReqlAst: %s", pojo, e.getMessage()));
    }
}
}

结果

$ scala ccreflect.Test
private final java.lang.String ccreflect.User.userId
private final java.lang.String ccreflect.User.loginInfo
private final scala.Option ccreflect.User.firstName
private final scala.Option ccreflect.User.lastName
private final scala.Option ccreflect.User.fullName
private final scala.Option ccreflect.User.email
private final scala.Option ccreflect.User.avatarURL
{firstName=None, lastName=None, avatarURL=None, loginInfo=xxx, fullName=None, userId=Bob, email=None}