Как избежать непроверенных предупреждений о приведении с помощью Java Generics

Как-то закрыли мой старый вопрос, поэтому открываю новый:

Я использую Java Generics для реализации общей двунаправленной хеш-карты из SQL-запроса. Он должен иметь возможность отображать любую комбинацию пар String, Integer вперед и назад. Его следует использовать так:

String sql = "SELECT string_val, int_val FROM map_table";
PickMap<String, Integer> pm1 = new PickMap<String, Integer>(sql);

String key1 = "seven";
Integer value1 = pm1.getLeft2Right(key1);

Integer key2 = 7;
String value2 = pm1.getRightToLeft(key2);

Конечно, должна быть возможность создать pm (Integer, Integer) и так далее ...

Моя реализация Pick Map выглядит так (без геттера ...):

public class PickMap<L, R> {

    private final HashMap<L, R> left2Right = new HashMap<L, R>();
    private final HashMap<R, L> right2Left = new HashMap<R, L>();

    public PickMap(String sql) throws OException {
        DTable d = new DTable(sql);
        int colTypeL = d.t.getColType(1);
        int colTypeR = d.t.getColType(2);
        Extractor<L> extLeft  = (Extractor<L>) getInstance(colTypeL);
        Extractor<R> extRight = (Extractor<R>) getInstance(colTypeR);    
        int numRows = d.t.getNumRows();
        for(int i=1;i<=numRows;i++) {
            L leftVal = extLeft.extract(d, i);
            R rightVal = extRight.extract(d, i);
            this.left2Right.put(leftVal, rightVal);
            this.right2Left.put(rightVal, leftVal);
        }
    }

    private Extractor<?> getInstance(int type) {
        if(type == 1)
            return new IntExtractor();
        else
            return new StringExtractor();
    }
}

interface Extractor<E> {
    E extract(DTable source, int row);
}

class IntExtractor implements Extractor<Integer> {

    @Override
    public Integer extract(DTable source, int row) {
        int value = 5;
        return new Integer(value);
    }
}

class StringExtractor implements Extractor<String> {

    @Override
    public String extract(DTable source, int row) {
        String retVal = "hello";
        return retVal;
    }
}

У меня нет ошибок компилятора, и я почти уверен, что так и будет. НО я получаю непроверенные предупреждения о приведении в методах "getInstance". Где я приводил Extractor (E) в Extractor (L) ...

Как мне правильно забросить? Или что мне не хватает? Или я должен просто подавить эти предупреждения?


person Sauer    schedule 29.02.2012    source источник


Ответы (3)


Вы получаете предупреждения, потому что нельзя доказать, что то, что вы делаете, безопасно. Вы предполагаете, что getInstance(colTypeL) вернет Extractor<L>, но это нельзя проверить ни во время компиляции, ни во время выполнения.

Вы можете использовать @SuppressWarnings("unchecked"), как упоминалось другими, но я бы попытался несколько переосмыслить дизайн.

person Jon Skeet    schedule 29.02.2012
comment
Да, я понимаю вашу точку зрения. Я хотел бы использовать общий тип L для создания экземпляра моего экстрактора. Поэтому вместо того, чтобы передавать colType методу getInstance, я хотел бы сделать что-нибудь вроде getInstance (L) и getInstance (R) ... Возможно ли это? Ненавижу подавляющие предупреждения! - person Sauer; 29.02.2012
comment
@Sauer: Вам нужно знать L и R во время выполнения, что обычно означает наличие параметров конструктора типа Class<? extends L> и Class<? extends R> или чего-то подобного. - person Jon Skeet; 29.02.2012
comment
Одна из возможностей - заставить конструктор взять необходимые ему экстракторы: PickMap(String sql, Extractor<? extends L> leftExtractor, Extractor<? extends R> rightExtractor>). Это не только делает компиляцию безопасной, но и позволяет кому-то другому прийти и решить, что им нужен PickMap<BigDecimal,Date>, без необходимости изменять код PickMap (при условии, что Extractor - это интерфейс или класс, к которому у них есть доступ). - person yshavit; 29.02.2012

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

@SuppressWarnings("unchecked")

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

person Richard Walton    schedule 29.02.2012

Если вы используете Spring Framework, вы можете использовать CastUtils:

import static org.springframework.data.util.CastUtils.cast;
obj.setString(cast(someObject));
String bob = cast(someObject);
person user11058144    schedule 17.05.2019