Безопасность типов: для выражения типа Map [] требуется непроверенное преобразование для соответствия Map[] - PullRequest
0 голосов
/ 29 декабря 2018

У меня есть следующие две строки:

Map<String,Object>[] IEXDivMap = null;       

IEXDivMap =  new Map[IEXJsonArray.length()];

и я получаю предупреждение:

The expression of type Map[] needs unchecked conversion to conform to Map<String,Object>[]

Есть ли способ исправить это?

ОБНОВЛЕНИЕ:

В комментариях меня спросили, зачем нам нужен массив Map для начала.Мы получаем серию хэш-карт и помещаем каждую в массив карты.Вот код:

@SuppressWarnings("unchecked")
public static Map<String,Object>[] getDiv(String ticker) {
    Map<String,Object>[] IEXDivMap = null;
    try{
        String url = "https://api.IEXtrading.com/1.0/stock/" + ticker + "/dividends/1y"; 
        URL obj = new URL(url);   

        HttpURLConnection con = (HttpURLConnection) obj.openConnection();       
        con.setRequestMethod("GET");
        int responseCode = con.getResponseCode();
        if(responseCode == 404){
            System.out.println("Ticker " + ticker + " NOT FOUND in getDiv()!");
            return IEXDivMap;                
        }else if (responseCode != 200){
            System.out.println("IEX Printing All Response Header for URL: " + obj.toString() + "\n");
            Map<String, List<String>> map = con.getHeaderFields();            
            for(Map.Entry<String, List<String>> entry : map.entrySet()) {
                System.out.println("IEX " + entry.getKey() + " : " + entry.getValue());
            }
        }

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuilder response = new StringBuilder();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);             
        }
        in.close();

        JSONArray IEXJsonArray = new JSONArray(response.toString());        
        IEXDivMap = new Map[IEXJsonArray.length()];

        for (int i = 0; i < IEXJsonArray.length(); i++) {
            IEXDivMap[i] = new HashMap<String,Object>();
            JSONObject IEXJsonObject = IEXJsonArray.getJSONObject(i);

            IEXDivMap[i].put("exDate",IEXJsonObject.getString("exDate"));
            IEXDivMap[i].put("amount",IEXJsonObject.getString("amount"));

            //System.out.println(IEXDivMap[i]);
            System.out.println(IEXDivMap[i].get("exDate") + " 0  " + IEXDivMap[i].get("amount"));
        }
    }catch(Exception e){
        System.out.println("FATAL ERROR: Something went wrong in getDiv " + e.getMessage());
        System.exit(0);
    }
    return IEXDivMap; 
}

Ответы [ 5 ]

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

Невозможно избежать предупреждения.

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

IEXDivMap = (Map<String, Object>[]) new Map[IEXJsonArray.length()];

или

IEXDivMap = (Map<String, Object>[]) new Map<?,?>[IEXJsonArray.length()];

но тогда это вызовет непроверенное предупреждение о касте, поэтому вы обмениваете одно предупреждение на другое.

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

Я не вижу неотъемлемого преимущества использования массива над коллекцией, подобной List, для вашего случая использования.Просто измените ваш код, чтобы использовать вместо него List, что гарантирует безопасность типов и устраняет необходимость в индексировании и т. П.

Важные вещи, которые изменятся:

  • Как вы объявляете свой тип возврата

    public static List<Map<String,Object>> getDiv(String ticker) 
    
  • Как вы создаете экземпляр держателя

    List<Map<String,Object>> IEXDivMap = new ArrayList<>();
    
  • Как вы заполнить карту (вид, вы просто измените способ ее ссылки)

    Map<String, Object> divMap = new HashMap<>();
    
0 голосов
/ 30 декабря 2018

К сожалению, невозможно решить проблему чистым способом.

Чистым решением будет создание универсального массива, но это невозможно из-за стирания типа.

Почему универсальныйсоздание массива запрещено?

Рассмотрим следующий пример с массивами:

Object[] arr = new String[1];
arr[0] = 10;

Результат ArrayStoreException.

Теперь представьте, что создание универсального массива разрешено:

Map<String, String>[] map = new Map<>[1]; // This is illegal
Object[] objects = map;
objects[0] = new HashMap<Integer, Integer>(); // No ArrayStoreException

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

Обходные пути?

Цитирование Обобщения Java faq Вы можете использовать:

  • массив необработанного типа
  • массив неограниченного параметризованного типа с подстановочными знаками
  • коллекция вместо массива

Лично я настоятельно рекомендую вам использовать List:

List<Map<String, Object>> list = new ArrayList<>();
0 голосов
/ 30 декабря 2018

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

Так что, если вы действительно хотите массив Map<String,Object> элементов (и по какой-то причиневместо этого нельзя использовать List), вы можете объявить переменную с этим универсальным типом, но вы всегда получите это предупреждение при сохранении только что созданного массива, поскольку он может иметь только необработанный тип.

Но это только предупреждение, и ваш код будет работать отлично.Это предупреждение, а не ошибка, означающее, что есть что-то, что требует внимания разработчика, поскольку компилятор не может решить, нормально это или нет.

Так в чем же проблема, вызывающая предупреждение?

Во время выполнения Map<String,Object>[] - это просто Map[], так как универсальные типы стираются во время компиляции.Таким образом, создание массива дает правильный тип времени выполнения массива, и вы не получите ClassCastException из этого назначения.Проверка общих правил выполняется только во время компиляции: обязанность компилятора - убедиться, что переменная времени выполнения Map[], назначенная переменной Map<String,Object>[], содержит только карты, в которых строки используются в качестве ключей, а объекты в качестве значений (и, конечно, null значения также допустимы в качестве элементов массива.)

Теперь, если вы присваиваете значение Map[] времени компиляции переменной Map<String,Object>[],

Map[] rawArray = ...;
Map<String,Object>[] generic Array = rawArray;

Компилятор не знает, какие типы ключей и значений используют карты, содержащиеся в rawArray, поэтому он справедливо предупреждает вас об этом риске несовместимости типов.Но в случае только что созданного new Map[n],

Map<String,Object>[] genericArray = new Map[5];

компилятор просто недостаточно интеллектуален, чтобы видеть, что этот массив содержит только свои начальные значения null, и, таким образом, полностью соответствует Map<String,Object>[] требования.Это утверждение на самом деле не содержит какого-либо риска, связанного с типами, просто компилятор недостаточно умен, чтобы его понимать.

Поэтому я рекомендую либо игнорировать предупреждение, либо размещать соответствующую аннотацию @SuppressWarnings,комментируя, почему оправдано подавление предупреждения.Жаль, что мы не можем применить аннотацию @SuppressWarnings к отдельному оператору, поэтому вы можете реорганизовать создание массива в собственный метод, поэтому аннотация @SuppressWarnings применяется только к этому действию, а не к вашему.весь метод.

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

Может, вот так?

import java.util.Map;
import java.util.HashMap;

public class test {
  public static void main(String[] args) {
    class MyMap extends HashMap<String,Object> { }
    MyMap[] IEXDivMap = null;       

    IEXDivMap = new MyMap[2];
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...