Может (a == 1 && a == 2 && a == 3) оценивать true в Java?

Мы знаем, что это возможно в JavaScript .

Но возможно ли напечатать сообщение «Успех» при условии, приведенном ниже в Java?

if (a==1 && a==2 && a==3) { System.out.println("Success"); } 

Кто-то предложил:

 int _a = 1; int a = 2; int a_ = 3; if (_a == 1 && a == 2 && a_ == 3) { System.out.println("Success"); } 

Но делая это, мы меняем фактическую переменную. Есть ли другой путь?

Да, это довольно легко добиться с помощью нескольких streamов, если вы объявите переменную a как изменчивую.

Один stream постоянно меняет переменную a от 1 до 3, а другой stream постоянно проверяет, что a == 1 && a == 2 && a == 3 . Это случается достаточно часто, чтобы на консоли непрерывно отображался stream «Успех».

(Обратите внимание, что если вы добавите предложение else {System.out.println("Failure");} , вы увидите, что тест проходит гораздо чаще, чем ему удается.)

На практике это также работает без объявления как изменчивого, но только 21 раз на моем MacBook. Без volatile компилятору или HotSpot разрешено кэшировать или заменять оператор if (false) . Скорее всего, HotSpot запускается через некоторое время и компилирует его на инструкции по сборке, которые кэшируют значение a . С volatile , он сохраняет печать «Успех» навсегда.

 public class VolatileRace { private volatile int a; public void start() { new Thread(this::test).start(); new Thread(this::change).start(); } public void test() { while (true) { if (a == 1 && a == 2 && a == 3) { System.out.println("Success"); } } } public void change() { while (true) { for (int i = 1; i < 4; i++) { a = i; } } } public static void main(String[] args) { new VolatileRace().start(); } } 

Используя концепции (и код) из блестящего ответа на гольф для гольфа , значения Integer могут быть испорчены.

В этом случае он может сделать int s casted для Integer s равным, если они обычно не будут:

 import java.lang.reflect.Field; public class Test { public static void main(String[] args) throws Exception { Class cache = Integer.class.getDeclaredClasses()[0]; Field c = cache.getDeclaredField("cache"); c.setAccessible(true); Integer[] array = (Integer[]) c.get(cache); // array[129] is 1 array[130] = array[129]; // Set 2 to be 1 array[131] = array[129]; // Set 3 to be 1 Integer a = 1; if(a == (Integer)1 && a == (Integer)2 && a == (Integer)3) System.out.println("Success"); } } 

К сожалению, это не так изящно, как многопоточный ответ Эрвина Болвидта (так как для этого требуется заклинание Integer ) , но все же некоторые забавные махинации происходят.

В этом вопросе @aioobe предлагает (и советует) использовать препроцессор C для classов Java.

Хотя это очень мошенничество, это мое решение:

 #define a evil++ public class Main { public static void main(String[] args) { int evil = 1; if (a==1 && a==2 && a==3) System.out.println("Success"); } } 

Если выполняется с использованием следующих команд, он выдает ровно один Success :

 cpp -P src/Main.java Main.java && javac Main.java && java Main 

Поскольку мы уже знаем, что этот код можно сделать истинным благодаря большим ответам Эрвина Болвидта и Ффлака , я хотел показать, что вам нужно уделять повышенное внимание при работе с условием, которое выглядит как представленное в вопросе, поскольку иногда то, что вы видите, может быть не совсем так, как вы думаете.

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

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

Я использовал кириллицу «а», которая является отличным символом латинского «а». Вы можете проверить символы, используемые в инструкции if здесь .

Это работает, потому что имена переменных берутся из разных алфавитов. Они представляют собой разные идентификаторы, создавая две разные переменные с различным значением в каждом.

Обратите внимание: если вы хотите, чтобы этот код работал правильно, кодировка символов должна быть заменена на одну, поддерживающую оба символа, например, все кодировки Unicode (UTF-8, UTF-16 (в BE или LE), UTF-32, даже UTF-7 ), или Windows-1251, ISO 8859-5, KOI8-R (спасибо – Thomas Weller и Paŭlo Ebermann – за указание):

 public class A { public static void main(String[] args) { int а = 0; int a = 1; if(а == 0 && a == 1) { System.out.println("Success!"); } } } 

(Надеюсь, вам никогда не придется иметь дело с такими проблемами в будущем).

Есть еще один способ приблизиться к этому (в дополнение к неустойчивому подходу к использованию данных, который я опубликовал ранее), используя мощь PowerMock. PowerMock позволяет заменять методы другими реализациями. Когда это сочетается с автоматической распаковкой, исходное выражение (a == 1 && a == 2 && a == 3) без изменений может быть выполнено.

@ Ответ phflack основан на изменении процесса автоматического бокса в Java, который использует Integer.valueOf(...) . Integer.intValue() подход основан на изменении автоматической Integer.intValue() вызов Integer.intValue() .

Преимущество нижеследующего подхода заключается в том, что исходный if-statement, заданный OP в вопросе, используется без изменений, что, я думаю, является самым элегантным.

 import static org.powermock.api.support.membermodification.MemberMatcher.method; import static org.powermock.api.support.membermodification.MemberModifier.replace; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @PrepareForTest(Integer.class) @RunWith(PowerMockRunner.class) public class Ais123 { @Before public void before() { // "value" is just a place to store an incrementing integer AtomicInteger value = new AtomicInteger(1); replace(method(Integer.class, "intValue")) .with((proxy, method, args) -> value.getAndIncrement()); } @Test public void test() { Integer a = 1; if (a == 1 && a == 2 && a == 3) { System.out.println("Success"); } else { Assert.fail("(a == 1 && a == 2 && a == 3) != true, a = " + a.intValue()); } } } 

Поскольку это, похоже, является продолжением этого вопроса JavaScript , стоит отметить, что этот трюк и подобные работы также работают на Java:

 public class Q48383521 { public static void main(String[] args) { int aᅠ = 1; int ᅠ2 = 3; int a = 3; if(aᅠ==1 && a==ᅠ2 && a==3) { System.out.println("success"); } } } 

На Ideone


Но обратите внимание, что это не самое худшее, что вы могли бы сделать с Unicode. Использование белых пробелов или управляющих символов, которые являются действительными частями идентификаторов или с использованием разных букв, которые выглядят одинаково, все же создает идентификаторы, которые различны и могут быть замечены, например, при выполнении текстового поиска.

Но эта программа

 public class Q48383521 { public static void main(String[] args) { int ä = 1; int ä = 2; if(ä == 1 && ä == 2) { System.out.println("success"); } } } 

использует два идентификатора, которые являются одинаковыми, по крайней мере, с точки зрения Unicode. Они просто используют разные способы кодирования одного и того же символа ä , используя U+00E4 и U+0061 U+0308 .

На Ideone

Поэтому, в зависимости от используемого инструмента, они могут не только выглядеть одинаково, но и текстовые инструменты с поддержкой Unicode могут даже не сообщать о какой-либо разнице, всегда находя их при поиске. Возможно, у вас может возникнуть проблема с тем, что разные представления теряются при копировании исходного кода кому-то другому, возможно, попытка получить помощь для «странного поведения», что делает его невоспроизводимым для помощника.

Вдохновленный отличным ответом @ Erwin, я написал аналогичный пример, но используя Java Stream API .

Интересно, что мое решение работает, но в очень редких случаях (поскольку компилятор just-in-time оптимизирует такой код).

Трюк заключается в отключении любых оптимизаций JIT с использованием следующей опции VM :

 -Djava.compiler=NONE 

В этой ситуации число успешных случаев значительно возрастает. Вот код:

 class Race { private static int a; public static void main(String[] args) { IntStream.range(0, 100_000).parallel().forEach(i -> { a = 1; a = 2; a = 3; testValue(); }); } private static void testValue() { if (a == 1 && a == 2 && a == 3) { System.out.println("Success"); } } } 

PS Параллельные streamи используют ForkJoinPool под капотом, а переменная a делится между несколькими streamами без какой-либо синхронизации, поэтому результат не является детерминированным.

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

 int a = 1; if (a / Float.POSITIVE_INFINITY == 1 / Float.POSITIVE_INFINITY && a / Float.POSITIVE_INFINITY == 2 / Float.POSITIVE_INFINITY && a / Float.POSITIVE_INFINITY == 3 / Float.POSITIVE_INFINITY) { System.out.println("Success"); } 
  • Показать Анимированный GIF
  • декомпиляция DEX в исходный код Java
  • Java: проблема неразрешенной компиляции
  • Не удается разрешить метод getMap ()
  • возобновление деятельности извещения
  • Добавить строки из-за использования общей ошибки 'extends' вызывает ошибку компилятора
  • Вызов внешней функции classа из внутреннего classа
  • API формата номера телефона Java
  • Как обрабатывать возвращаемое значение из AsyncTask
  • String.replaceAll без RegEx
  • Как вы реализуете FileObserver из службы Android
  • Interesting Posts

    Как получить версию Windows в качестве переменной?

    RegEx соответствует номерам, разделенным запятой, с необязательной десятичной частью

    GCC создает общий объект вместо исполняемого двоичного кода

    Запись PCM записанных данных в WAV-файл (java android)

    ?? Null Coalescing Operator -> Что означает коалесцирование?

    Сравнение встроенных баз данных Java

    свойство classа маркировки c # как грязное

    Как отключить автоматический формат номера Excel

    Может ли вирус виртуальной виртуальной машины влиять на главный компьютер?

    Управление группами пользователей и ролями в .NET с помощью Active Directory

    Как перенести данные и настройки Google Chrome на другой аккаунт Google?

    «Не удается найти корневое устройство» в новой установке ArchLinux

    Почему удаленный рабочий стол (RDP) недостаточно быстрый для просмотра видео на удаленном ПК?

    Как я могу дать eclipse больше памяти, чем 512M?

    Установка Windows XP не распознает жесткий диск нетбука

    Давайте будем гением компьютера.