【问题标题】:How do I reflect a private static nested subclass?如何反映私有静态嵌套子类?
【发布时间】:2020-02-10 04:33:47
【问题描述】:

首先,我在 Kotlin 中寻找答案,但我正在与 Java 库进行交互。

我需要从一个私有静态嵌套类中获取一个实例,该实例派生自周围超类的一个实例。

假设您有这些(简化的)嵌套 Java 类

public abstract class GLFWKeyCallback extends Callback implements GLFWKeyCallbackI {

  public static GLFWKeyCallback create(GLFWKeyCallbackI instance) {
    new Container(instance.address(), instance);
  }

  private static final class Container extends GLFWKeyCallback {

    private final GLFWKeyCallbackI delegate;

    Container(long functionPointer, GLFWKeyCallbackI delegate) {
      super(functionPointer);
      this.delegate = delegate;
    }
  }
}

我通过另一种外部方法以 GLFWKeyCallback 的形式返回一个 Container 实例。你可以把这个方法想成:

public static GLFWKeyCallback getCallback() {
  return GLFWKeyCallback.create(anInternalInstance)
}

在 Kotlin 中:

val callback:GLFWKeyCallback = getCallback()

// I would now want to cast,
// or in other ways use callback
// as the GLFWKeyCallback.Container class it actually is.

val callbackAsContainer = callback as GLFWKeyCallback.Container // Error: Container is private

val ContainerClass = GLFWKeyCallback::class.nestedClasses.find { it.simpleName?.contains("Container") ?: false }!!
// Gives me a KClass<*> that I don't know how to use, can't find documentation for this kind of circumstance

// If using the class instance itself is not possible I would at least want to get the
// Container.delegate of GLFWKeyCallbackI

val delegateField = ContainerClass.memberProperties.findLast { it.name == "delegate" }!!
val fieldValue = field.get(callback)
// Error: Out-projected type 'KProperty1<out Any, Any?>' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'

【问题讨论】:

  • 首先,我想确定您确实需要引用私有静态嵌套类,因为这很难闻。 (一方面,它不是第三方库的公共接口的一部分,因此在未来的版本中可能会被更改/重命名/删除。另一方面,对库的内部进行处理可能会导致它意外中断方式。)当然,有时确实有必要——但你需要确定没有其他选择。
  • @gidds 你绝对是对的,但这次我需要。

标签: java kotlin kotlin-reflect


【解决方案1】:

为什么不想使用 Java 反射?你也可以从 Kotlin 中使用它:

val callback = getCallback()
val field = callback::class.java.getDeclaredField("delegate")
field.isAccessible = true
val delegate = field.get(callback) as GLFWKeyCallbackI

【讨论】:

    【解决方案2】:

    您仍然可以通过.getClass() 获取课程。此示例打印“5”:

    public class Example {
        public static void main(String[] args) throws Exception {
            Object o = Target.get();
            Field f = o.getClass().getDeclaredField("field");
            f.setAccessible(true);
            Integer i = (Integer) f.get(o);
            System.out.println(i);
        }
    }
    
    public class Target {
        public static Object get() { return new Inner(); }
        private static class Inner {
            private int field = 5;
        }
    }
    

    如果你知道准确的名字:

    Class<?> c = Class.forName("com.foo.pkgof.Target$Inner");
    c.getDeclaredField("field");
    

    有效。注意美元。这是“外部”和“内部”之间使用的分隔符。

    【讨论】:

    • 感谢您的回答,但我无法让它在 kotlin 中用于我的用例。我可能只是在翻译中遗漏了一些东西。如果我也在用 java 编写测试用例,它很可能会很好。
    • @Karlsson 请参阅kotlinlang.org/docs/reference/reflection.html – kotlin 反射不像 java 反射,但那篇文章解释了如何回到 java 反射。
    猜你喜欢
    • 2016-01-05
    • 2014-08-30
    • 1970-01-01
    • 2020-02-16
    • 2011-12-25
    • 2023-04-07
    • 2013-03-06
    • 1970-01-01
    • 2017-02-10
    相关资源
    最近更新 更多