Невозможно получить токены типа от объектов класса? - PullRequest
0 голосов
/ 20 декабря 2018

Допустим, у меня есть универсальный интерфейс, который реализован различными классами.

public interface MyInterface<K, V> {
    // Some method declarations
    // ...
    // But owing to Java type erasure, we also have...
    Class<K> getKClass();
    Class<V> getVClass();
}

Теперь я использую хранилище объектов для получения конкретных экземпляров классов, которые реализуют MyInterface.И я не знаю во время написания кода типы параметров K и V.Но возможно получить доступ к соответствующим Class объектам, которые были сохранены заранее.Теперь я мог использовать их при запросе фабрики.

public MyInterface getObjectFromStore(String uniqueKey, 
      Class kClazz, Class vClazz) {
    MyInterface concreteInstance = MyClassWarehouse.retrieveObject(uniqueKey);

    // Perform type checks.
    boolean kMismatch = !kClazz.isAssignableFrom(concreteInstance.getKClass());
    boolean vMismatch = ...;
    // Mismatch handling...
    ...

    // Everything's okay
    return concreteInstance;
}

Мне кажется, что код выглядел бы намного чище, если бы я мог написать свой метод следующим образом:

public <K, V> MyInterface<K, V> getObjectFromStore(String uniqueKey) {
    try {
        MyInterface<K, V> concreteInstance = MyClassWarehouse.retrieveObject(uniqueKey);
        return concreteInstance;
    } catch (ClassCastException cce) {
        // Better way to handle type mismatch
        ...
    }
}

Но для этого необходимо, чтобы я знал классы на момент написаниякод.

MyInterface<String, Double> retrievedObject = getObjectFromStore("key123");

Поскольку у меня есть только объекты классов, я должен использовать первый, "неуклюжий" подход.В частности:

// Must use this...
MyInterface retrievedObject = getObjectFromStore("key123", kClazz, vClazz);

// ... because this (or anything equivalent) is not possible.
MyInterface<kClazz, vClazz> retrievedObject = getObjectFromStore("key123");

Мне кажется, что поскольку типы не являются истинными объектами в Java, нет способа получить токены типов K и V из объектов классов kClazz и vClazzтаким образом, что позволило бы второй подход.Тем не менее, синтаксический сахар был бы хорош.

Есть ли еще одна причина, по которой он не был включен?

1 Ответ

0 голосов
/ 20 декабря 2018

Если вы отбрасываете проверку во время компиляции в пользу проверки во время выполнения, вам понадобятся объекты типа времени выполнения из двух источников для проведения каких-либо сравнений.

Итак, самое простое - указать Class объект с обоих концов.В простом случае.

<T> void put(Class<T> t, T object);
<T> T get(Class<T> t);

Добавление определенного типа с двумя параметрами (в Java нет типов с более высоким родом), двух типов и ключа (свысока для строкового программирования).

<K,V> void put(Class<K> k, Class<V> v, Key key, My<K,V> object);
<K,V> My<K,V> get(Class<K> k, Class<V> v, Key key);

Существует возможность объединить три ключевых объекта в один.

public final class MyKey<K,V> {
    public static of(Class<K> k, Class<V> v, SimpleKey key) {
        ....
    }
    ...
}
<K,V> void put(MyKey<K,V> key, My<K,V> object);
<K,V> My<K,V> get(MyKey<K,V> key);

Кроме того, вы можете искать другой источник объектов класса.Они доступны из сигнатур методов.

public interface MyReceiver<K,V> {
    void accept(My<K,V> object);
}
/** @param receiver Runtime type should specialise type parameters. */    
void get(MyReceiver<?,?> receiver); 

(MyReciever<?,?> может быть стандартным Consumer<? extends MyReciever<?,?>>.)

Вы можете добавить дополнительный простой ключ в качестве параметра к get(лямбда-дружественный), метод на MyReceiver, аннотация на accept или MyReceiver, или отбросьте метод с MyReceiver и используйте любой тип среды выполнения, используемый в качестве имени метода (возможно, аннотированный, чтобы найти, какой метод выхочу).

Фактически этот подход , указывающий требуемые типы в интерфейсах, является более современным, чем разнородные карты старой школы .

(Обратите внимание, что "хранилище" - этостандартный срок для вашего склада.)

...