Статические методы не могут подвергаться полиморфному поведению. Это не имеет большого смысла. Создайте этот вариант использования, предположив, что вы хотите:
public void foo(MyInterface i) {
i.getInstance("abc");
}
теперь я хочу вызвать этот метод с реализацией MyInterface
(класс A
), но поскольку я не могу передать класс, мне нужно передать объект:
A a = new A();
foo(a);
теперь внутри foo
переопределение static
getInstance
вызывается в экземпляре класса A
. Итак, теперь я застрял в создании объекта, чтобы вызвать статический метод.
Я хочу сказать, что вы все равно должны были бы создать объект в большинстве случаев полиморфизма, поскольку в вашем исходном интерфейсе метод был метод экземпляра.
==
все равно проверит равномерность объекта. Однако легко обмануть:
Integer a = 10;
Integer b = 10;
System.out.println(a == b); //prints true
Integer c = new Integer(10);
Integer d = new Integer(10);
System.out.println(c == d); //prints false
Ваши примеры с неравенствами будут работать, поскольку они не определены в объектах. Однако при сравнении ==
все равно будет проверяться равенство. В этом случае, когда вы инициализируете объекты из примитива в штучной упаковке, используется тот же объект (для a и b). Это хорошая оптимизация, поскольку примитивные классы ящиков неизменяемы.
этот метод сравнивает два целых числа с нулевой проверкой, см. тесты
public static boolean compare(Integer int1, Integer int2) {
if(int1!=null) {
return int1.equals(int2);
} else {
return int2==null;
}
//inline version:
//return (int1!=null) ? int1.equals(int2) : int2==null;
}
//results:
System.out.println(compare(1,1)); //true
System.out.println(compare(0,1)); //false
System.out.println(compare(1,0)); //false
System.out.println(compare(null,0)); //false
System.out.println(compare(0,null)); //false
System.out.println(compare(null,null)); //true
Objects.equals(x,y)
вместо того, чтобы кататься самостоятельно.
– ryvantage
8 June 2017 в 04:04
Нет, == между Integer, Long и т. д. будет проверяться на ссылочное равенство - то есть
Integer x = ...;
Integer y = ...;
System.out.println(x == y);
, это будет проверять, относятся ли x
и y
к тот же объект , а не , равный объектам.
Таким образом,
Integer x = new Integer(10);
Integer y = new Integer(10);
System.out.println(x == y);
гарантированно печатает false
. Интерполяция «малых» значений автобокса может привести к сложным результатам:
Integer x = 10;
Integer y = 10;
System.out.println(x == y);
Это будет печатать true
из-за правил бокса ( JLS раздел 5.1.7 ) , По-прежнему используется ссылочное равенство, но ссылки действительно равны .
Лично я бы использовал:
if (x.intValue() == y.intValue())
или
if (x.equals(y))
Последнее немного менее эффективно - нет перегрузки для Integer.equals(Integer)
, поэтому ему придется выполнять проверку типа времени выполнения, тогда как первый использует тот факт, что мы уже знаем, что оба объекта Integer
s.
К счастью, compareTo
знает о типах, поэтому:
if (x.compareTo(y) < 0)
все равно будет эффективным. Конечно, это область микрооптимизации, и вы должны использовать код, который вы найдете наиболее ясным - после того, как убедитесь, что он прав:)
Как вы говорите, для любого сравнения между типом оболочки (Integer
, Long
и числовой тип (int
, long
и т. д.) значение типа оболочки - unboxed , и тест применяется к примитивным значениям.
происходит как часть двоичной цифровой рекламы ( JLS раздел 5.6.2 ). Посмотрите документацию каждого отдельного оператора, чтобы узнать, применяется ли она. Например, из документов для == и! = ( JLS 15.21.1 ):
Если операнды оператора равенства являются как числовыми, так и один из них имеет числовой тип, а другой является конвертируемым (п. 5.1.8) в числовой тип, двоичная цифровая продвижение выполняется в операндах (§5.6.2).
и для & lt; , & lt; =,> and> = ( JLS 15.20.1 )
Тип каждого из операндов оператора цифрового сравнения должен быть типом, который является (§5.1.8) к примитивному числовому типу, или возникает ошибка времени компиляции. Бинарное числовое продвижение выполняется в операндах (§5.6.2). Если продвинутый тип операндов является int или long, выполняется сопоставление целого числа со знаком; если этот продвинутый тип является float или double, выполняется сравнение с плавающей запятой.
Обратите внимание, что ничто из этого не рассматривается как часть ситуации, когда ни тип является числовым.
x.compareTo(y) < 0
вместо x < y
?
– Max Nanasy
29 August 2015 в 01:06
==
проверяет ссылочное равенство, однако при написании кода типа:
Integer a = 1;
Integer b = 1;
Java достаточно умен, чтобы повторно использовать неизменное значение для a
и b
, поэтому это верно: a == b
. Любопытно, что я написал небольшой пример, показывающий, где java останавливает оптимизацию таким образом:
public class BoxingLol {
public static void main(String[] args) {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
Integer a = i;
Integer b = i;
if (a != b) {
System.out.println("Done: " + i);
System.exit(0);
}
}
System.out.println("Done, all values equal");
}
}
Когда я компилирую и запускаю это (на моей машине), я получаю:
Done: 128
Начиная с Java 1.7 вы можете использовать Objects.equals :
java.util.Objects.equals(oneInteger, anotherInteger);
Возвращает true, если аргументы равны друг другу и false в противном случае. Следовательно, если оба аргумента равны null, возвращается true, и если только один аргумент имеет значение null, возвращается false. В противном случае равенство определяется с помощью метода equals первого аргумента.
Вызов
if (a == b)
Будет работать большую часть времени, но он не всегда будет работать, поэтому не используйте его.
Самый правильный способ сравнения двух целых чисел классы для равенства, считая, что они называются 'a' и 'b', должны вызывать:
if(a != null && a.equals(b)) {
System.out.println("They are equal");
}
Вы также можете использовать этот способ, который немного быстрее.
if(a != null && b != null && (a.intValue() == b.intValue())) {
System.out.println("They are equal");
}
На моей машине 99 миллиардов операций заняли 47 секунд, используя первый метод, и 46 секунд, используя второй метод. Вам нужно будет сравнить миллиарды значений, чтобы увидеть разницу.
Обратите внимание, что «a» может быть пустым, поскольку это объект. Сравнение таким образом не приведет к исключению нулевого указателя.
Для сравнения большего и меньшего, используйте
if (a != null && b!=null) {
int compareValue = a.compareTo(b);
if (compareValue > 0) {
System.out.println("a is greater than b");
} else if (compareValue < 0) {
System.out.println("b is greater than a");
} else {
System.out.println("a and b are equal");
}
} else {
System.out.println("a or b is null, cannot compare");
}
if (a==b)
работает только для небольших значений и не будет работать большую часть времени.
– Tony
30 August 2017 в 15:04
tl; dr Мое мнение состоит в том, чтобы использовать унарный +
, чтобы вызвать unboxing на одном из операндов при проверке равенства значений и просто использовать математические операторы в противном случае. Обоснование следует:
Уже упоминалось, что сравнение ==
для Integer
- сравнение идентичности, которое обычно не то, что хочет программист, и что целью является сравнение значений; Тем не менее, я сделал немного science о том, как сделать это сравнение наиболее эффективно, как с точки зрения компактности, правильности и скорости кода.
Я использовал обычную кучу методов :
public boolean method1() {
Integer i1 = 7, i2 = 5;
return i1.equals( i2 );
}
public boolean method2() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2.intValue();
}
public boolean method3() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2;
}
public boolean method4() {
Integer i1 = 7, i2 = 5;
return i1 == +i2;
}
public boolean method5() { // obviously not what we want..
Integer i1 = 7, i2 = 5;
return i1 == i2;
}
и получил этот код после компиляции и декомпиляции:
public boolean method1() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
return var1.equals( var2 );
}
public boolean method2() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method3() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method4() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method5() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2 == var1 ) {
return true;
} else {
return false;
}
}
Как вы можете легко видеть, метод 1 вызывает Integer.equals()
(очевидно), методы 2-4 приведут к точно к тому же коду , разворачивая значения с помощью .intValue()
, а затем сравнивая их напрямую, а метод 5 просто запускает сравнение идентичности, являясь неправильным способом сравнения значений.
Поскольку (как уже упоминалось, например, JS) equals()
несет накладные расходы (он должен делать instanceof
и неконтролируемый отбор), методы 2-4 будут работать с точно такой же скоростью, заметно лучше, чем метод 1, когда используется в жестких петлях, поскольку HotSpot вряд ли оптимизирует отливки & amp; instanceof
.
Это очень похоже на другие операторы сравнения (например, <
/ >
) - они вызовут unboxing, в то время как использование compareTo()
не будет - но на этот раз операция очень оптимизирован HS, поскольку intValue()
- всего лишь метод getter (главный кандидат на оптимизацию).
На мой взгляд, редко используемая версия 4 является наиболее кратким способом - каждый опытный разработчик C / Java знает, что унарный плюс в большинстве случаев равен касту на int
/ .intValue()
- в то время как для некоторых (немного) WTF момент для некоторых (в основном тех, кто не использовал унарный плюс в своей жизни ), он, возможно, показывает намерение наиболее четко и наиболее кратко - он показывает, что мы хотим значение int
одного из операндов, заставляя другое значение также распаковываться. Также неоспоримо наиболее похож на обычном i1 == i2
сравнение используется для примитивных int
значений
Мой голос идет на i1 == +i2
и усилитель. i1 > i2
для объектов Integer
, как для производительности, так и для причинам согласованности. Он также переносит код в примитивы, не изменяя ничего, кроме объявления типа. Использование названных методов похоже на введение семантического шума для меня, похоже на сильно критикуемый стиль bigInt.add(10).multiply(-3)
.
unary +
(унарный плюс), см., Например, [Д0] stackoverflow.com/questions/2624410/…
– vaxquis
13 July 2018 в 21:56
200
, оба теста будут печататьfalse
. – Daniel Earwicker 4 October 2009 в 00:11equals
, называемого". – Jon Skeet 4 October 2009 в 08:03