==
выполняет контрольную проверку равенства, ссылаясь на то, что 2 объекта (строки в этом случае) относятся к одному и тому же объекту в памяти.
Метод equals()
будет проверять, будет ли содержимое или состояния двух объектов одинаковы.
Очевидно, что ==
работает быстрее, но во многих случаях может (может) давать ложные результаты, если вы просто хотите сказать, имеет ли 2 String
s тот же текст.
Определенно рекомендуется использовать метод equals()
.
Не беспокойтесь о производительности. Некоторые способы поощрения использования String.equals()
:
String.equals()
сначала проверяет ссылочное равенство (используя ==
), и если две строки одинаковы по ссылке, дальнейший расчет Выполняется! String.equals()
будет проверять длину строк. Это также является быстрой операцией, поскольку класс String
хранит длину строки, не нужно считать символы или кодовые точки. Если длины отличаются, дальнейшая проверка не выполняется, мы знаем, что они не могут быть равными. Когда все сказано и даже если у нас есть гарантия, что строки являются стажерами, использование метода equals()
все еще не является издержками, которые можно было бы подумать, определенно рекомендуемым способом. Если вам нужна эффективная проверка ссылок, используйте перечисления, где гарантируется спецификацией и реализацией языка, что одно и то же значение перечисления будет одним и тем же объектом (по ссылке).
Ну, аннотация, документирующая намерение, была бы бесполезной, если вы предполагаете, что всегда есть это намерение.
Вы назвали пример AutoCloseable
, который, очевидно, не предназначен который будет реализован как функция, так как существует Runnable
, что намного удобнее для функции с сигнатурой ()->void
. Предполагается, что класс, реализующий AutoCloseable
, управляет внешним ресурсом, который анонимные классы, реализованные с помощью лямбда-выражения, не выполняет.
Более ясным примером является Comparable
, а interface
не только не предназначено реализованный в виде лямбда-выражения, невозможно реализовать его правильно с использованием лямбда-выражения.
interface
с помощью @FunctionalInterface
на примере: interface
имеет семантику языка программирования, например AutoClosable
или Iterable
(это вряд ли произойдет для ваших собственных интерфейсов) interface
имеет произвольные реализации и / или больше идентификатор, чем фактическая реализация, например. java.net.ProtocolFamily
или java.lang.reflect.GenericArrayType
(обратите внимание, что последний также наследует реализацию default
для getTypeName()
, которая бесполезна для лямбда-реализаций, полагаясь на toString()
) interface
] должны иметь личность, например java.net.ProtocolFamily
, java.nio.file.WatchEvent.Modifier
и т. д. Обратите внимание, что они обычно реализуются с помощью enum
. Другим примером является java.time.chrono.Era
, который имеет только один метод abstract
, но его спецификация говорит: Экземпляры Era
можно сравнить с помощью оператора ==
. »interface
предназначен для изменения поведения операции, для которой реализация interface
не наследует / реализует что-либо иначе не имеет смысла, например java.rmi.server.Unreferenced
java.io.Closeable
, java.io.Flushable
, java.lang.Readable
java.awt
: ActiveEvent
должен быть реализован с помощью AWTEvent
, PrinterGraphics
на Graphics
, то же самое относится к java.awt.print.PrinterGraphics
(эй, два interface
s для точно такой же вещи ...), javax.print.FlavorException
должен быть реализован подклассом javax.print.PrintException
@FunctionalInterface
для симметрии с другим прослушивателем событий нескольких методов, t функциональные интерфейсы, но на самом деле прослушиватели событий являются хорошими кандидатами на лямбда-выражения. Если вы хотите удалить слушателя позднее, вы должны сохранить экземпляр, но это не отличается от, например, (g12) interface
, следует ли ее аннотировать и, следовательно, сосредоточить внимание на основных кандидатах на то, чтобы быть используется в функциональном контексте. Я уверен, что, например, java.io.ObjectInputValidation
, java.lang.reflect.InvocationHandler
, juc RejectedExecutionHandler
& amp; ThreadFactory
не будет плохой как @FunctionalInterface
, но я не знаю, будет ли, например. java.security.spec.ECField
делает хорошего кандидата. Чем более общей является библиотека, тем более вероятным пользователям библиотеки будет возможность ответить на этот вопрос для конкретного interface
, который им интересен, но было бы несправедливо настаивать на том, чтобы разработчик библиотеки ответил на него для все . В этом контексте имеет смысл видеть присутствие @FunctionalInterface
в качестве сообщения о том, что interface
определенно предназначено для использования вместе с лямбда-выражениями, чем рассматривать отсутствие аннотации в качестве индикатора того, что он не предназначен для использования таким образом. Это точно так же, как компилятор справляется с этим, вы можете реализовать каждый абстрактный метод interface
с использованием лямбда-выражения, но когда присутствует аннотация, гарантирует , что вы можете использовать этот interface
в этом путь. Планируемое расширение. Просто потому, что интерфейс соответствует требованиям SMI, теперь не означает, что расширение не понадобится позже.
abstract
к interface
в любом случае нарушает совместимость. Он сомневается, что есть планы сделать это.
– Holger
27 January 2015 в 09:45
@FunctionalInterface
в interface
и удалить его в более поздней версии, не нарушая ничего. Но это не отвечает на вопрос , который посвящен API JDK i>
– Holger
28 January 2015 в 17:57
В java 8 функциональный интерфейс представляет собой интерфейс, имеющий только один абстрактный метод, называемый функциональным методом, к которому сопоставляются параметр и тип возвращаемого выражения lambda.
java.util.function
содержит функциональные интерфейсы общего назначения, используемые JDK, а также для конечных пользователей. Хотя они не являются полным набором функциональных интерфейсов, к которым могут быть применены лямбда-выражения, но они обеспечивают достаточно для удовлетворения общих требований.
Существует множество таких интерфейсов, которые заслуживают того, чтобы их можно было назвать функциональным интерфейсом, но пакет java.util.function
уже предоставляет функциональные интерфейсы для наших почти всех
Например, посмотрите на следующий код.
public interface Comparable<T> {
public int compareTo(T o);
}
@FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable
также может взять объект и получить некоторое значение типа int, но есть более общий выделенный интерфейс ToIntFunction
для выполнения этой задачи. Нет такого жесткого правила, что все заслуживающие интерфейсы должны быть аннотированы с помощью @FunctionalInterface
, но чтобы получить преимущество лямбда-функции, интерфейс должен выполнять все критерии, определенные FunctionalInterface.
Comparable
с выражением лямбда, и ваш пример просто показывает недопустимую реализацию, пытаясь это сделать.
– Didier L
28 January 2018 в 14:02
Comparator
принимает два типаT
и сравнивает их - этоToIntBiFunction<T,T>
.Comparable
сравнивает сам i> с каким-либо другим типом - у лямбды (почти) нет чувства самости, поэтому это невозможно реализовать в качестве лямбда. – Boris the Spider 27 January 2015 в 10:31Comparable
требует симметрии, т. Е.a.compareTo(b) == -b.compareTo(a)
, что невозможно гарантировать лямбда-выражение; вы даже не можете объявить лямбду реализоватьComparable<T>
, когдаT
является классом лямбда, поскольку класс лямбда не указан. – Holger 27 January 2015 в 10:34AutoClosable
иIterable
, хотя я знаю, что это не входит в рамки намерений создателя интерфейса. Всегда есть намеренное использование и фактическое использование, и вы должны быть осторожны, чтобы не двигаться слишком далеко от предполагаемого использования, однако было бы странно, если бы мы все были всегда на пути, предвиденном основными разработчиками ... – Holger 27 January 2015 в 10:48