Предупреждения в Java при приведении к универсальному типу - PullRequest
8 голосов
/ 20 февраля 2010

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

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

Что у меня есть:

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);

Ответы [ 5 ]

3 голосов
/ 20 февраля 2010

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

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

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));
    ...
    }
2 голосов
/ 20 февраля 2010

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

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");
1 голос
/ 20 февраля 2010

Это объект SharedContext, который вы написали? Если это так, возможно ли заменить универсальное сопоставление String-> Object конкретными полями?

например.

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

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

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

0 голосов
/ 20 февраля 2010

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

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

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

0 голосов
/ 20 февраля 2010

Как назначается переменная context? Это из параметра ctx, который имеет тип:

SharedContext<Object>

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

...