2015-07-01 2 views
0

Рассмотрим это:Как определить, что устаревший метод будет принимать типы Nullable?

@Nullable Object obj = null; 
Optional<Object> optional = Optional.ofNullable(obj); 

Это терпит неудачу, потому что шахматная структура предполагает ofNullable не может принимать null значения (в конце концов, его параметр не помеченных как @Nullable).

Есть ли хороший способ проверить рамки проверки, что этот метод (или другие методы в устаревшем коде, который я не могу изменить), принимает типы @Nullable везде, не изменяя код везде?

+1

Это, по-видимому, является текущим ограничением рамки. Решение, на мой взгляд, состоит в том, чтобы позволить настраиваемой конфигурации добавлять аннотации типа к внешним библиотекам (по-моему, по умолчанию предполагается, что все ненулевое значение прекрасное), включая Java SDK. Например, позвольте мне добавить в конфигурационный файл следующее объявление: « Необязательный java.util.Optional.ofNullable (@Nullable T t)», который «переопределит» фактическое определение. Разумеется, он должен просто добавить аннотации типа, не изменять их и не путать с типами возвращаемых/параметров. – Renato

+0

Это устранит необходимость иметь «аннотированный JDK» и позволяет добавлять аннотации в любую библиотеку. – Renato

+0

Это не текущее ограничение рамки, потому что предлагаемая вами функция уже существует и называется [заглушками классов] (http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html# заглушки). Его можно использовать в сочетании с аннотированным JDK. – mernst

ответ

1

EDIT: этот ответ был основан на @mernst помощь в комментариях и в Checker Framework's Issue tracker

Если вы, как и я, не хотят или не могут использовать аннотированный JDK, вы столкнетесь с этой проблемой.

Примечание: В большинстве магазинов Java, с которыми я работал, мы просто не можем переключить какой компилятор мы используем или предоставить «пользовательский» JDK (это действительно немыслимо). Для того, чтобы быть переносимым, мне пришлось бы добавить пользовательский JDK в исходный репозиторий, для начала или распространить его на каждую машину, включая серверы CI, где компилируется код, и убедитесь, что они находятся на одном и том же пути по разным ОС. Просто не круто.

Решение должно предоставить stub classes и передать их в качестве аргумента в процесс javac.

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

Например, с помощью Maven (с использованием стандартного compiler plugin):

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-compiler-plugin</artifactId> 
    <version>3.1</version> 
    <configuration> 
     <source>1.8</source> 
     <target>1.8</target> 
     <annotationProcessors> 
      <annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor> 
     </annotationProcessors> 
     <compilerArgs> 
      <arg>-Astubs=checkerframework/stubs</arg> 
      <arg>-AstubWarnIfNotFound</arg> 
     </compilerArgs> 
    </configuration> 
</plugin> 

Кроме того, необходимо добавить эти зависимости для вашего проекта:

<dependency> 
     <groupId>org.checkerframework</groupId> 
     <artifactId>checker-qual</artifactId> 
     <version>1.9.2</version> 
     <optional>true</optional> 
    </dependency> 
    <dependency> 
     <groupId>org.checkerframework</groupId> 
     <artifactId>checker</artifactId> 
     <version>1.9.2</version> 
     <optional>true</optional> 
    </dependency> 

Здесь checkerframework/stubs является каталогом (по отношению к местоположение пом), содержащий заглушки. Необязательно, мой заглушка выглядит так (как ни странно, заглушки должны быть названы * .astub, поэтому этот файл называется необязательным.astub):

package java.util; 

import org.checkerframework.checker.interning.qual.*; 

import javax.annotation.Nullable; 

class Optional<T> { 
    static <T> Optional<T> ofNullable(@Nullable T value); 

    @Nullable T orElse(@Nullable T other); 
} 

Этот подход прост, требует мало работы, не связывайтесь с какой компилятор использовать или библиотеки Java на всех, убеждаются эти определения используются только с checkerframework (так что я могу, для например, добавьте это в профиль Maven и включите его, только если я хочу просто передать аргумент Maven), будет работать через машины и ОС без предварительной настройки в истинном Java-способе делать что-то.

0

Я не уверен, почему вы говорите «его параметр не отмечен как @Nullable». Когда я смотрю на файл шахматных рамки/проверки/JDK/nullness/SRC/Java/Util/Optional.java, я вижу следующий аннотированный метод:

public static <T> Optional<@NonNull T> ofNullable(@Nullable T value) { 
    return value == null ? empty() : of(value); 
} 

Кроме того, когда я запустить Framework Checker по следующему коду он не предупреждает.

// run like this: 
// javacheck -g TestOptional.java -processor nullness 

import java.util.*; 
import org.checkerframework.checker.nullness.qual.Nullable; 
import org.checkerframework.checker.nullness.qual.NonNull; 

public class TestOptional { 

    void m() { 

    @Nullable Object obj = null; 
    Optional<Object> optional1 = Optional.ofNullable(obj); 

    } 

} 

Я не уверен, что происходит в вашем случае, потому что вы не предоставили полный тестовый случай, вы не сказали, какую команду вы запускали, и вы не дали реальное сообщение об ошибке , (Вы поставили диагноз, но я не уверен, что это точно.)

Возможно, предоставление более подробной информации позволит лучше понять вашу проблему.

+0

Вы сделали предположение, что я использую аннотированный JDK, которого нет, и я упомянул об этом в комментариях. Зная это, больше ничего не имеет значения. Я запускаю NullnessChecker как простой обработчик аннотации (в Maven, но это не имеет значения). Использование аннотированного JDK определенно невозможно (он не переносимый, это может вызвать проблемы совместимости/безопасности, даже кажется, что он полностью избыточен, учитывая возможность предоставления классов-заглушек - возможно, у вас должны быть добавлены заглушки для Jdk8 по умолчанию и исключить аннотированный JDK). – Renato

+0

Кроме того, ваш ответ не затрагивает мой более общий вопрос: «Есть ли хороший способ проверить checker-framework, что этот метод (или другие методы в устаревшем коде, который я не могу изменить) ...». – Renato

+0

О, вы не используете аннотированный JDK. Вы не сказали этого в комментариях или в другом месте. Почему бы не использовать его? Это будет простой способ решить вашу проблему. Что касается аннотирования устаревшего кода, мой первоначальный комментарий уже направил вас на обсуждение руководства [классы-заглушки] (http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html#stub). Я вижу, что вы теперь повторили это в своем ответе (но не отдавая должное моему комментарию). Во всяком случае, я рад, что вы теперь понимаете. – mernst