Предупреждения в Java при кастинге к универсальному типу

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

Как я могу избавиться от аннотации?

То, что я имею:

public MyObject(SharedContext<Object> ctx) {
    super(ctx); // set protected field 'context'
    ...
    context.set("Input Fields"  ,Collections.synchronizedMap(new TreeMap<String,Pair<String,Boolean>>(String.CASE_INSENSITIVE_ORDER)));
    context.set("Output Fields" ,Collections.synchronizedMap(new TreeMap<String,String>              (String.CASE_INSENSITIVE_ORDER)));
    context.set("Event Registry",new EventRegistry(log)                                                                              );
    }

@SuppressWarnings("unchecked")
protected void startup() {
    inputFields     =(Map<String,Pair<String,Boolean>>)context.get("Input Fields"  ,null);
    outputFields    =(Map<String,String>              )context.get("Output Fields" ,null);
    eventRegistry   =(EventRegistry                   )context.get("Event Registry",null);
    ...
    }

Защищенный переменный контекст является типом SharedContext<Object>.

Без аннотации компилятор дает предупреждения:

...\MyClass.java:94: warning: [unchecked] unchecked cast
found   : java.lang.Object
required: java.util.Map<java.lang.String,com.mycompany.Pair<java.lang.String,java.lang.Boolean>>
    inputFields     =(Map<String,Pair<String,Boolean>>)context.get("Input Fields"  ,null);
                                                                  ^
...\MyClass.java:95: warning: [unchecked] unchecked cast
found   : java.lang.Object
required: java.util.Map<java.lang.String,java.lang.String>
    outputFields    =(Map<String,String>              )context.get("Output Fields" ,null);
8
задан Lawrence Dol 20 February 2010 в 08:30
поделиться

5 ответов

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

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

public class Generics
{

static public void main(String[] args) {
    Generics.test();
    }

static private void test() {
    Map<String,Object> ctx=new TreeMap<String,Object>();
    Map<String,Object> map=new TreeMap<String,Object>();
    Map<String,Object> tst;

    ctx.put("Test",map);
    tst=uncheckedCast(ctx.get("Test"));
    }

@SuppressWarnings({"unchecked"})
static public <T> T uncheckedCast(Object obj) {
    return (T)obj;
    }

}

В другом блоге предлагалось усовершенствовать этот служебный метод:

@SuppressWarnings("unchecked") 
public static <T, X extends T> X uncheckedCast(T o) {
    return (X) o;
    }

принудительное использование того, что возвращается, как подкласс переданного параметра.

Предполагая, поместите uncheckedCast в класс общедоступной утилиты GenUtil, мой метод запуска в вопросе не будет выдавать (бесполезных) предупреждений и будет выглядеть так:

protected void startup() {
    inputFields  =GenUtil.uncheckedCast(context.get("Input Fields"  ,null));
    outputFields =GenUtil.uncheckedCast(context.get("Output Fields" ,null));
    eventRegistry=GenUtil.uncheckedCast(context.get("Event Registry",null));
    ...
    }
3
ответ дан 5 December 2019 в 22:17
поделиться

Какую версию компилятора вы используете? С компилятором Java 6 (Sun JDK windows) я не видел подробного предупреждения. Я получаю предупреждение только при использовании флага '-Xlint:unchecked'.

Попробуйте -Xlint:-unchecked и сообщите нам, решит ли это вашу проблему. Подробнее о флагах,

http://java.sun.com/javase/6/docs/technotes/tools/windows/javac.html

0
ответ дан 5 December 2019 в 22:17
поделиться

Как назначается переменная контекста ? Это из параметра ctx, имеющего тип:

SharedContext<Object>

?

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

0
ответ дан 5 December 2019 в 22:17
поделиться

Первое неконтролируемое приведение может быть устранено путем определения неуниверсального класса, расширяющего универсальный Map < String, Pair > и сохранение этого в SharedContext вместо общего TreeMap , например (используя ForwardingMap из Guava ):

class InputFieldMap extends ForwardingMap<String,Pair<String,Boolean>> {

    private final Map<String,Pair<String,Boolean>> delegate =
        Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER);
    protected Map<String,Pair<String,Boolean>> delegate() { return delegate; }

}

// ...

context.set("Input Fields"  ,Collections.synchronizedMap(new InputFieldMap()));

// ...

inputFields     =(InputFieldMap)context.get("Input Fields"  ,null);
outputFields    =(Map<?,?>     )context.get("Output Fields" ,null);

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

String bar = String.valueOf(outputFields.get("foo"));

или обернуть карту:

Map<?, String> wrappedOutputFields    =
    Maps.transformValues(outputFields, Functions.toStringFunction());

// ...

String bar = wrappedOutputFields.get("foo");
2
ответ дан 5 December 2019 в 22:17
поделиться

Вы написали объект SharedContext? Если да, то можно ли заменить обычное отображение String-> Object определенными полями?

например.

context.setInputFields(...)
context.setOutputFields(...)
context.setEventRegistry(...)
context.getInputFields()
etc.

Универсальный объект контекста для хранения всех данных всегда кажется мне не совсем идеальным решением. Особенно с дженериками и непроверенными сообщениями приведения в результате.

В качестве альтернативы вы можете создать объект-оболочку под названием SoftwareMonkeyContext, который имеет определенные методы установки / получения, как указано выше, и внутренне использует ваш метод GenUtil.uncheckedCast. Это избавит вас от необходимости использовать GenUtil.uncheckedCast в нескольких местах вашего кода.

1
ответ дан 5 December 2019 в 22:17
поделиться
Другие вопросы по тегам:

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