String
в Java является неизменным.Следующий фрагмент, в общем и целом, «неправильный».
String s = "hello world!";
s.toUpperCase(); // "wrong"!!
System.out.println(s); // still "hello world!"!!!
Несмотря на то, что этот код «неправильный», код компилируется и запускается, возможно, в замешательстве многих новичков, которым нужно либо сказать, в чем ошибкаили выяснить это самостоятельно, посмотрев документацию.
Чтение документации является важной частью понимания API, но мне интересно, может ли это быть дополнено дополнительными проверками во время компиляции.В частности, мне интересно, возможно, можно использовать среду аннотаций Java для обеспечения того, чтобы значение, возвращаемое определенными методами, не игнорировалось.Разработчики API / авторы библиотек затем использовали бы эту аннотацию в своих методах для документирования, возвращаемые значения не должны игнорироваться.
Как только API дополнен этой аннотацией (или, возможно, другим механизмом), тогда всякий раз, когда пользователь пишеткод, подобный приведенному выше, он не будет компилироваться (или делать это со строгим предупреждением).
Так можно ли это сделать, и как бы вы поступили так, как это?
Приложение: Мотивация
Кажется очевидным, что в общем случае Java должна позволять игнорировать возвращаемые значения методов.Возвращенные значения методов, таких как List.add
( всегда true
), System.setProperty
(предыдущее значение), вероятно, можно игнорировать большую частьtimes.
Однако существует также много методов, возвращаемые значения которых NOT следует игнорировать.Это почти всегда является ошибкой программиста или, иначе, не правильным использованием API.Они включают в себя такие вещи, как:
- Методы для неизменяемых типов (например,
String
, BigInteger
и т. Д.), Которые возвращают результат операций вместо изменения экземпляра, который вызываетсяon. - Методы, возвращаемое значение которых является критической частью его поведения и не должно игнорироваться, но люди иногда так или иначе делают (например,
InputStream.read(byte[])
возвращает количество прочитанных байтов, которое должно NOT принимается за всю длину массива)
В настоящее время мы можем писать коды, которые игнорируют эти возвращаемые значения и позволяют их компилировать и запускать без предупреждения.Статические анализаторы / средства поиска ошибок / средства обеспечения стиля / и т. Д. Почти наверняка могут пометить их как возможные запахи кода, но может показаться целесообразным / идеальным, если это может быть реализовано самим API, возможно, с помощью аннотаций.
Для класса почти невозможно гарантировать, что он всегда используется «должным образом», но есть вещи, которые он может сделать, чтобы помочь клиентам правильно их использовать (см .: Effective Java 2nd Edition, Item 58: Использовать отмеченные исключения длявосстанавливаемые условия и исключения времени выполнения для ошибок программирования и Элемент 62: Документируйте все исключения, создаваемые каждым методом ).Наличие аннотации, которая заставляла бы клиентов не игнорировать возвращаемые значения определенных методов, и применение ее компилятором во время компиляции в форме ошибок или предупреждений, казалось бы, соответствовало этой идее.
Приложение 2. Фрагмент
Ниже приведена предварительная попытка, которая кратко иллюстрирует, чего я хочу достичь:
@interface Undiscardable { }
//attachable to methods to indicate that its
//return value must not be discarded
public class UndiscardableTest {
public static @Undiscardable int f() {
return 42;
}
public static void main(String[] args) {
f(); // what do I have to do so this generates
// compilation warning/error?
System.out.println(f()); // this one would be fine!
}
}
Приведенный выше код компилируется и работает нормально (как видно на ideone.com ).Как я могу сделать это не так?Как я могу назначить семантику, которую я хочу @Undiscardable
?