Как отразить закрытый статический вложенный подкласс? - PullRequest
0 голосов
/ 02 февраля 2019

Во-первых, я ищу ответ в 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, с помощью другого внешнего метода.Вы можете думать об этом методе как:

  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'


Любая помощь будет хорошей, решения не должны выглядеть красиво.Это для тестовых случаев, а не для производственного кода.

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Вы все еще можете получить класс через .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");

работает.Обратите внимание на доллар.Это разделитель для использования между «внешним» и «внутренним».

0 голосов
/ 02 февраля 2019

почему вы не хотите использовать отражение Java?Вы можете использовать его также из Kotlin :) Для меня это прекрасно работает

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