Подтвердить что ты не робот

Java, объявить переменную с несколькими интерфейсами?

В Java можно объявить поле/переменную, тип которой - несколько интерфейсов? Например, мне нужно объявить Map, а также Serializable. Я хочу убедиться, что переменная ссылается на сериализуемую карту. Интерфейс Map не расширяет Serializable, но большинство реализаций Map Serializable.

Я уверен, что ответ отрицательный.

Follow after. Я полностью осведомлен о создании нового интерфейса, который расширяет как Map, так и Serializable. Это не будет работать, поскольку существующие реализации (например, HashMap) не реализуют мой новый интерфейс.

4b9b3361

Ответ 1

Нет необходимости объявлять поле/переменную таким образом. Тем более, что это может быть проверено только временем выполнения, а не временем компиляции. Создайте сеттер и сообщите об ошибке, если переданная карта не реализует Serializable.

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

Ответ 2

Вы можете сделать это с помощью дженериков, но это не красиво:

class MyClass<T,K,V extends Serializable & Map<K,V>> {

   T myVar;

}

Ответ 3

public interface MyMap extends Map, Serializable {
}

определит новый интерфейс, являющийся объединением Map и Serializable.

Очевидно, что вам необходимо обеспечить соответствующую реализацию этого (например, MyMapImpl), и затем вы можете предоставить переменные ссылки типа MyMap (или Map или Serializable, в зависимости от требований).

Чтобы устранить ваши разъяснения, вы не можете модифицировать поведение (например, сериализуемую карту). Вы должны иметь интерфейс и некоторую соответствующую реализацию.

Ответ 4

Это можно сделать с помощью некоторых трюков дженериков:

    public <T extends Map<?,?> & Serializable> void setMap(T map)

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

Ответ 5

Вы можете добиться этого, создав свой собственный интерфейс, который расширяет требуемые интерфейсы.

public interface SerializableMap<K, V> extends Map<K, V>, Serializable {

}

Ответ 6

Я проголосовал за Брайана, но хотел добавить немного более высокого уровня мысли.

Если вы просмотрите SDK, вы обнаружите, что они редко (если когда-либо) проходят вокруг реальных объектов коллекции.

Причина в том, что это не очень хорошая идея. Коллекции чрезвычайно незащищены.

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

Я видел два решения: нужно всегда извлекать массив и передавать его. Это делает SDK.

Другой заключается в том, чтобы ВСЕГДА переносить коллекции в родительский класс (и я имею в виду инкапсуляцию, а не расширение). Я привык к этой привычке, и это очень важно. Это ничего не стоит, потому что вы все равно не дублируете все методы сбора (на самом деле вы редко дублируете любой из них). Фактически то, что вы делаете, это перемещение функциональности "Утилиты" из других классов, распределенных по всему вашему коду, в класс-оболочку, где и должно быть в первую очередь.

Любой метод с подписями, который соответствует "method (collection,...)", должен быть почти наверняка является элементом-членом этой коллекции, как и любые петли, которые перебирают по коллекции.

Мне просто нужно выкидывать это время от времени, потому что это одна из тех вещей, которые я не получал на некоторое время (потому что никто не защищал концепцию). Кажется, что у него будет некоторый недостаток, но, сделав это некоторое время, и увидев проблемы, которые он решил и устранил, он не может даже представить себе какие-либо возможные недостатки, это просто все хорошо.

Ответ 7

Вы не можете этого сделать, если хотите продолжать использование существующих реализаций Map.

Альтернативой может быть создание вспомогательного класса и добавление метода, подобного этому:

public static Serializable serializableFromMap(Map<?, ?> map) {
    if (map instanceof Serializable) {
        return (Serializable)map;
    }
    throw new IllegalArgumentException("map wasn't serializable");
}

Ответ 8

Нет, вам в значительной степени нужно бросить.