Scala扩展未发现的特征字段

chr*_*007 2 java reflection scala traits

我有一个scala特征,其公共UUID具有默认值:

trait pet {
    var uuid_ : UUID = UUID.randomUUID
}
Run Code Online (Sandbox Code Playgroud)

现在我在scala中创建了多个类:

class dog extends pet {
    var foo = 1
}
class cat extends pet {
}
class fish extends pet {
}
Run Code Online (Sandbox Code Playgroud)

之后我在Java中创建了一个方法(两个语言混合的旧项目).
这里剪了我的问题.在变量somePet是一个实例dog,catfish.但目前尚不清楚它们究竟是什么:

// printing all variables in the console for human testing
Serializer.printAllFields(somePet);

// The somePet Variable must be a pet
if(!pet.class.isAssignableFrom(somePet.getClass()))
    throw new Exception("Not a pet.");

// get the UUID of the pet
UUID uuid_;
try {
    Field f = pet.class.getField("uuid_");
    f.setAccessible(true);
    uuid_ = (UUID) f.get(somePet);
}catch(Exception e){
    // no uuid found
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

但是当我运行代码时,我收到以下错误:

Exception in thread "main" java.lang.NoSuchFieldException: uuid_
Run Code Online (Sandbox Code Playgroud)

并且堆栈跟踪指向该行Field f = pet.class.getField("uuid_");.
但是代码有什么问题?
我认为另一种替代方法是用以下内容替换以下内容

Field f = ntObj.getClass().getField("uuid_");
Run Code Online (Sandbox Code Playgroud)

但这也失败了.
那么变量在哪里uuid_
因为当我somePet使用Serializer 打印出当前控制台中的所有变量时,我会得到类似的东西

* cat.uuid_ = 34d7a781-472d-4d98-861e-7cff08045445;
Run Code Online (Sandbox Code Playgroud)

要么

* dog.foo = 1
* dog.uuid_ = 34d7a781-472d-4d98-861e-7cff08045445;
Run Code Online (Sandbox Code Playgroud)

在控制台中.
所以变量uuid_有一个默认值.
(我在这篇文章中使用的是序列化程序)

那么如何uuid_在我的java片段中获取变量?

Lpp*_*Edd 6

首先,Serializer包装下没有这样的java.util东西,所以你正在使用别的东西.

An trait被转换为Java interface,它本身不能包含字段.
但是,您正尝试通过Pet界面访问该字段

pet.class.getField(...)
Run Code Online (Sandbox Code Playgroud)

那不行.您需要在混凝土内寻找场地class.
此外,该字段将private默认为,因为访问是通过a授予的getter.

getField方法能够检索public整个类层次结构的每个字段(这意味着甚至是超类),同时getDeclaredField能够检索protectedprivate字段,但仅限于您从中调用它的确切类.你还需要打电话setAccessible(true),因为

值true表示反射对象在使用时应禁止Java语言访问检查.值false表示反射对象应强制执行Java语言访问检查

正确的代码将是(dog具体实例)

final Field uuid = dog.getClass().getDeclaredField("uuid_");
uuid.setAccessible(true);
final Object o = uuid.get(dog);
Run Code Online (Sandbox Code Playgroud)

或使用自动 getter

final Method uuid = dog.getClass().getMethod("uuid_");
final Object o = uuid_.invoke(dog);
Run Code Online (Sandbox Code Playgroud)