Как каждый инстанцирует массива карт в Java?

Объявление функции в протоколе дает указание компилятору использовать динамическую отправку при вызове функции, поскольку компилятор ожидает, что типы, реализующие протокол, предоставят реализацию для этой функции. Это называется method requirement. Если тип не определяет метод, то среда выполнения разрешает вызов метода методу, объявленному в расширении протокола.

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

Чтобы проиллюстрировать выше, рассмотрим следующий код:

protocol Shape {
    func draw()
}

extension Shape {
    func draw(){
        print("This is a Shape")
    }
}

struct Circle: Shape {
    func draw() {
        print("This is a Circle")
    }
}

struct Square: Shape {
    func draw() {
        print("This is a Square")
    }
}

let shapes: [Shape] = [Circle(), Square()]

for shape in shapes {
    shape.draw()
}

Вышеприведенный код будет иметь выход

This is a Circle 
This is a Square

Это связано с тем, что draw() является method requirement, что означает, что при вызове draw() , среда выполнения будет искать реализацию draw () в действительном типе элемента, в данном случае внутри Circle и Square.

Теперь, если мы не объявим draw как требование метода, что означает, что мы не упоминаем его в объявлении протокола

protocol Shape {
}

. Затем компилятор больше не будет использовать динамическую отправку и перейдет прямо к реализации, определенной в расширение протокола. Таким образом, код будет печатать:

This is a Shape
This is a Shape

Подробнее, если мы сбрасываем листинг элемента массива на тип, который, как мы ожидаем, он будет, мы получим статическое связывание назад. Это напечатает This is a Circle

if let circle = shapes[0] as? Circle {
    circle.draw()
}

, потому что компилятор теперь может сказать, что первый элемент из shapes является Circle, а поскольку Circle имеет метод draw(), он будет вызывать это.

Это способ Swift справиться с абстрактными классами: он дает вам возможность указать, что вы ожидаете от типов, соответствующих этому протоколу, и при этом допускать реализацию по умолчанию этих методов.

35
задан Karl von L 29 September 2009 в 17:42
поделиться

7 ответов

Я знаю, что немного поздно для ответа, но я нашел это обходное решение полезным для моего случая... Надежда это помогает!

Использование массив HashMap для хранения HashMaps..

public static void main(String[] args) {
    HashMap[] arr = new HashMap[1];//creating an array of size one..just for sake of example
    HashMap<String, String> arrMap = new HashMap<String, String>();

    //use loops to store desired key-value pairs into the HashMap which will be stored inside the array
    arrMap.put("ABC", "Name");

    //use loop to store your desired hashMap into the array at a particular index
    arr[0] = arrMap;

    //desired manipulation of the stored array.
    System.out.println(arr[0]);
}
1
ответ дан 27 November 2019 в 07:06
поделиться

Не совсем ответ на ваш вопрос, но рассматривали ли вы возможность использовать вместо него список ?

List<Map<String,Integer>> maps = new ArrayList<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());

, похоже, работает нормально.

См. Java теория и практика: подводные камни Generics для подробного объяснения того, почему смешивание массивов с generics не рекомендуется.

Обновление:

Как упоминалось Дрю в комментариях, может быть даже лучше использовать Collection интерфейс вместо Список . Это может пригодиться, если вам когда-нибудь понадобится перейти на Set или один из других подынтерфейсов из Collection . Пример кода:

Collection<Map<String,Integer>> maps = new HashSet<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());

С этой отправной точки вам нужно будет только изменить HashSet на ArrayList , PriorityQueue или любой другой класс, реализующий ] Коллекция .

39
ответ дан 27 November 2019 в 07:06
поделиться

You can't safely create a generic array. Effective Java 2nd Edition goes into the details in the chapter on Generics. Start at the last paragraph of page 119:

Why is it illegal to create a generic array? Because it isn’t typesafe. If it were legal, casts generated by the compiler in an otherwise correct program could fail at runtime with a ClassCastException. This would violate фундаментальная гарантия, предоставляемая система общих типов.

Чтобы сделать это более конкретным, рассмотрим следующий фрагмент кода:

 // Почему создание универсального массива недопустимо - не компилируется!
Список  [] stringLists = новый список  [1]; // (1)
Список <Целое число> intList = Arrays.asList (42); // (2)
Object [] objects = stringLists; // (3)
объекты [0] = intList; // (4)
Строка s = stringLists [0] .get (0); // (5)

Давайте представим, что строка 1, которая создает общий массив, допустимо. Строка 2 создает и инициализирует Список , содержащий единственный элемент. Строка 3 хранит Перечислить массив в объект переменная массива, что допустимо, потому что массивы ковариантны. Линия 4 магазинов Список в единственную element of the Object array, which succeeds because generics are implemented by erasure: the runtime type of a List instance is simply List, and the runtime type of a List[] instance is List[], so this assignment doesn’t generate an ArrayStoreException. Now we’re in trouble. We’ve stored a List instance into an array that is declared to hold only List instances. In line 5, we retrieve the sole element from the sole list in this array. The compiler automatically casts the retrieved element to String, but it’s an Integer, so we get a ClassCastException at runtime. In order to prevent this from happening, line 1 (which creates a generic array) generates a compile-time error.

Because arrays and generics don't combine well (as well as other reasons), it's generally better to use Collection objects (in particular List objects) rather than arrays.

19
ответ дан 27 November 2019 в 07:06
поделиться

Короткий ответ, похоже, таков: вы действительно просто не можете.

См. Следующий блог об этом. http://www.bloggingaboutjava.org/2006/01/java-generics-quirks/

One of the comments to the blog states that:

Actually, the engineers made the creation of such an Array illegal. So the creation of an array from generic Class fails. The Collection.toArray method followed by a Cast to the Array works at compile time.

This solves not the problem, that the ArrayStoreCheck can’t be done during Runtime, but you can create an Array of generics in this way.

As suggested by Bill the Lizard, you probably are better off using a

List<Map<String,Integer>>
2
ответ дан 27 November 2019 в 07:06
поделиться

I had a similar question, best response I got referred to this

-1
ответ дан 27 November 2019 в 07:06
поделиться
myMaps = new HashMap<String, Integer>[10]();

Значит, это неправильно

Почему бы не составить список карт вместо того, чтобы пытаться создать массив?

List<Map<String, Integer>> mymaps = new ArrayList<Map<String, Integer>>(count);
-5
ответ дан 27 November 2019 в 07:06
поделиться

В целом не рекомендуется смешивать универсальные шаблоны и массивы в Java, лучше использовать ArrayList.

Если вы должны использовать массив, лучший способ справиться с этим - поместить создание массива (ваш пример 2 или 3) в отдельный метод и аннотируйте его с помощью @SuppressWarnings ("unchecked").

5
ответ дан 27 November 2019 в 07:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: