Ошибка несоответствия типа в java 8

у меня есть следующий класс со следующим методом.

public class MyClass {

    public static <T> T getSomeThing(final int id, final java.lang.reflect.Type type, final Map<Integer, String> someThings) {
        final String aThing = someThings.get(id);
        if (aThing == null || aThing.isEmpty()) {
            return null;
        }
        return GsonHelper.GSON.fromJson(aThing, type);
    }

}

GsonHelper предоставляет мне некоторые com.google.gson.GsonBuilder

public class GsonHelper {

    public static final com.google.gson.Gson GSON = getGsonBuilder().create();

    public static GsonBuilder getGsonBuilder() {
        return new GsonBuilder().setPrettyPrinting()
                .enableComplexMapKeySerialization()
                .registerTypeAdapter(new com.google.gson.reflect.TypeToken.TypeToken<byte[]>() {
                    // no body
                }.getType(), new Base64TypeAdapter())
                .registerTypeHierarchyAdapter(Date.class, new DateTypeAdapter())
                .registerTypeHierarchyAdapter(Pattern.class, new PatternTypeAdapter())
                .registerTypeAdapterFactory(new ListTypeAdapterFactory())
                .registerTypeAdapterFactory(new MapTypeAdapterFactory())
                .registerTypeAdapterFactory(new SetTypeAdapterFactory());
    }
}

до Java 7 я использовал этот метод, как:

Map<Integer, String> allThings = new HashMap<>();
//FILL allThings with values

if(MyClass.getSomeThing(7, java.lang.Boolean.class, allThings)){
    //do something
}

это сработало отлично. потому что метод вернет логическое значение, и я могу использовать это внутри "если". Но когда я перехожу на Java 8, это больше невозможно. Компилятор жалуется на:

несоответствие типов: невозможно преобразовать из объекта boolean

 //while this is working but would throw a JsonSyntaxException
final String myString = "myInvalidJsonString";
if(GsonHelper.GSON.fromJson(myString, java.lang.Boolean.class)){
    //do something
}

Я знаю, что java.ленг.Boolean может быть null. И я мог бы решить эту проблему с помощью:

final Boolean b = MyClass.getSomeThing(7, java.lang.Boolean.class, allThings);
if(b){
    //do something
}

но мне интересно, почему это работает с Java 7, а не в Java 8. (не ответил)
что они изменили? (не ответил)
В чем причина этой ошибки компилятора при переходе с Java 8? (ответил)

2 ответов


метод public static <T> T getSomeThing(final int id, final java.lang.reflect.Type t, final Map<Integer, String> someThings) не гарантирует возврата Boolean. Он возвращается T который определяется вызывающим абонентом и может быть чем угодно, что означает Object.

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

почему бы не изменить подпись на boolean?

public static boolean getSomeThing(final int id,
                                   final java.lang.reflect.Type t,
                                   final Map<Integer, String> someThings)

или ты в поисках?

public static <T> T getSomeThing(final int id,
                                 final Class<T> clazz,
                                 final Map<Integer, String> someThings)

чем этот код будет компилироваться и работа:

public static void main(String[] args) {
    if (getSomeThing(7, Boolean.class, emptyMap())) {
        System.out.println("It works!");
    }
}

public static <T> T getSomeThing(final int id,
                                 final Class<T> clazz,
                                 final Map<Integer, String> someThings) {
    ...
}

последняя версия, где результат getSomeThing() назначена Boolean переменная может быть выведена в соответствии с JLS 8, потому что в контекстное задание цели типа Boolean lets T выводится как Boolean, действительно. Здесь все компиляторы согласны.

Что касается исходного случая, JLS 8 не классифицирует условие if-оператора как контекстное задание. Вне контекстов назначения или вызова вызов не является рассматривается как выражение poly, но как автономное выражение (JLS 15.12 1-й пуля). Автономные выражения не имеют целевого типа. Без вывода целевого типа в Java 8 возвращается к выводу T to Object.

команда Eclipse имеет запрошено разъяснение в этой связи даже до Java 8 GA. К сожалению,в результате выпуска остается нерешенным до сегодняшнего дня.

Ergo: JLS и наблюдаемое поведение javac Не согласен. вероятно, JLS-это объект, который должен быть исправлен.

обновление: JLS не собирается меняться (подтверждено по частной электронной почте), поэтому принятие программы является ошибкой в javac.