1-строчные операторы IF в Java - PullRequest
6 голосов
/ 02 февраля 2009

Возможно ли иметь операторы IF без скобок в Java, например:

if (x == y)
  z = x * y;
else
  z = y - x;

Это возможно в PHP, и я не уверен, что делаю что-то не так.

Уточнение: Вот мой фактический код, который я использую:

if (other instanceof Square)
    Square realOther = (Square) other;
else
    Rectangle realOther = (Rectangle) other;

Но я получил ошибки, такие как «Синтаксический токен на realOther, удалите этот токен» и «realOther не может быть разрешен» среди других.

Что я делаю не так?

Ответы [ 13 ]

17 голосов
/ 02 февраля 2009

Да, вы можете следовать за оператором if одним оператором без использования фигурных скобок (но вы действительно хотите?), Но ваша проблема более тонкая. Попробуйте изменить:

if (x=y)

до:

if (x==y)

Некоторые языки (например, PHP) обрабатывают любое ненулевое значение как истину, а ноль (или NULL, null, nil, как угодно) как false, поэтому операции присваивания в условных выражениях работают. Java допускает только логические выражения (выражения, которые возвращают или оценивают как логические) внутри условных операторов. Вы видите эту ошибку, потому что результатом (x=y) является значение y, а не true или false.

Вы можете увидеть это в действии на следующем простом примере:

if (1)
    System.out.println("It's true");

if (true)
    System.out.println("It's true");

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

Редактировать: Мое предположение на вашем обновленном примере (который вы должны были поставить в вопросе, а не в качестве нового ответа) заключается в том, что вы пытаетесь получить доступ к realOther после того, как назначите его в этих утверждениях , Это не будет работать, поскольку область действия realOther ограничена оператором if / else. Вам нужно либо переместить объявление realOther над оператором if (что в этом случае будет бесполезно), либо добавить больше логики в оператор if:

if (other instanceof Square)
    ((Square) other).doSomething();
else
    ((Rectangle) other).doSomethingElse();

Чтобы помочь в дальнейшем, нам нужно увидеть больше вашего фактического кода.

Редактировать: Использование следующего кода приводит к тем же ошибкам, которые вы видите (компилирование с gcj):

public class Test {
    public static void Main(String [] args) {
        Object other = new Square();

        if (other instanceof Square)
            Square realOther = (Square) other;
        else
            Rectangle realOther = (Rectangle) other;

        return;
    }
}

class Rectangle {
    public Rectangle() { }
    public void doSomethingElse() {
        System.out.println("Something");
    }
}

class Square {
    public Square() { }
    public void doSomething() {
        System.out.println("Something");
    }
}

Обратите внимание, что добавление фигурных скобок в этот оператор if / else сводит ошибку к предупреждению о неиспользуемых переменных. Наши собственные mmyers указывают:

http://java.sun.com/docs/books/jls/third_edition/html/statements.html говорит: «Каждая локальная переменная заявление заявление немедленно содержится в блоке. "Те, в if утверждение не имеет скобок вокруг их, поэтому они не находятся в блок.

Также обратите внимание, что мой другой пример:

((Square) other).doSomething()

компилируется без ошибок.

Редактировать: Но я думаю, что мы установили (хотя это интересное погружение в непонятные крайние случаи), что все, что вы пытаетесь сделать, вы делаете не правильно. Так что же вы на самом деле пытаетесь сделать?

4 голосов
/ 02 февраля 2009

Следующий код является допустимым:

int x = 5;
int y = 2;
int z = 0;

if (x == y)
  z = x * y;
else
  z = y - x;

Как упоминал Шон Брайт, ваша проблема в том, что вы пытаетесь проверить не булево выражение. Вы должны использовать оператор == вместо оператора = в предложении if.

Еще одна вещь, которую стоит упомянуть, это то, что многие считают плохой практикой пропускать использование фигурных скобок в выражении if-then-else. Это может привести к ошибкам в будущем, таким как добавление еще одного оператора в тело кодовых блоков if или else. Это тип ошибки, который может быть трудным для понимания.

Это на самом деле не проблема при использовании оператора if-else, потому что Java воспримет это как синтаксическую ошибку (оператор else без предшествующего if). Однако рассмотрим следующий оператор if:

if (x == y)
  z = y * x;

Теперь предположим, что позже вам нужно будет сделать больше вещей, если x == y. Вы можете легко сделать следующее, не осознавая ошибки.

if (x == y)
  z = y * x;
  w = x * y - 5;

Конечно, второй оператор w = x * y - 5 будет выполнен независимо от результата теста if оператора. Если бы у вас были фигурные скобки для начала, вы бы избежали этой проблемы.

if (x == y) {
  z = y * x;
  w = x * y - 5; // this is obviously inside the if statement now
}
3 голосов
/ 02 февраля 2009

Редактировать: чтобы быть более понятным, это ваша проблема:

Это:

if (other instanceof Square)
    Square realOther = (Square) other;
else
    Rectangle realOther = (Rectangle) other;

- это то же самое, что и это:

if (other instanceof Square) {
    Square realOther = (Square) other;
} else {
    Rectangle realOther = (Rectangle) other;
}

Обратите внимание, что вы никогда ничего не делаете с realOther. Вы определяете его там, но, поскольку он ограничен этим набором скобок, вы выбрасываете его, как только нажимаете на закрывающую скобку.

Отсутствие скобок не помогает, тот факт, что это оператор (после if) делает его независимым блоком кода, и как только этот блок выходит, realOther отбрасывается.

Java признает, что это так, и говорит вам (небрежно цитируя Иниго Монтойя): «Я не думаю, что это означает то, что вы думаете, что это значит».

Вторичная проблема, Java строго типизирована. Даже если он может разрешить синтаксис, как вы говорите, сразу после этого оператора if он должен иметь абсолютный конечный тип для realOther. Ваше заявление if полностью сломало бы мозг Java, потому что он не знал бы, должен ли realOther рассматриваться как прямоугольник или квадрат.

Предположим, что прямоугольник имеет метод setWidth и setHeight (а квадрат только что имеет setHeight). После этого оператора IF Java должна позволять вам вызывать setWidth или нет? Java ДОЛЖНА знать эти вещи во время компиляции (если нет, нам не понадобится приведение).

другое редактирование:

Чтобы исправить это, вы используете это:

// class Rectangle extends Square
// Both implement setHeight, Rect also implements setWidth.
public void reSize(Square other, int h, int w) {
    other.setHeight(h);

    if (realOther instanceof Rectangle) {
        ((Rectangle)realOther).setWidth(w);
}

Другими словами, вы должны работать со связанными объектами так, чтобы они оставались как более абстрактный объект как можно дольше, используя только конкретные объекты, когда вам нужно вызвать метод для этого объекта.

Если вы правильно написали код, вы почти всегда можете использовать более абстрактные и редко использовать конкретные. С квадратом и прямоугольником это неочевидно, квадрат / прямоугольник - довольно неряшливая проблема и используется в качестве примера некоторых трудных решений, которые вы должны принять с помощью ОО-программирования, но это действительно работает почти всегда - я очень редко приходится кастовать вообще ...

3 голосов
/ 02 февраля 2009

Если вам нужен один вкладыш, если это выражение, вы можете использовать троичный оператор

  final int myVal = predicate ? consequent : alternative;

что примерно равно

  final int myVal;
  if(predicate)
    myVal = consequent;
  else
    myVal = alternative;
3 голосов
/ 02 февраля 2009

Всегда обращайтесь к соглашениям по коду для языка программирования JavaTM :

В частности, см. Глава 7, Раздел 4 :

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

if (condition) //AVOID! THIS OMITS THE BRACES {}!
    statement;
2 голосов
/ 02 февраля 2009

Ваш код похож на этот?

if (other instanceof Square)
  Square realOther=(Square) other;
else
  Rectangle realOther=(Rectangle) other;

//...

realOther.doSomething();

Проблема в том, что в Java, в отличие от PHP, realOther не существует вне оператора if. Какой тип other? Это Object? Если да, есть ли общий базовый класс или интерфейс для Square и Rectangle? (Shape может быть?) Если это так, вы должны сделать что-то вроде этого:

Shape realOther = null;
if(other instanceof Shape)
  realOther = other;

//...

if(realOther != null)
  realOther.doSomething();
2 голосов
/ 02 февраля 2009

Это возможно (кроме опечатки / ошибки, на которую указал @Sean), но в зависимости от правил, которым вы следуете, это считается плохой формой.

Правила кодекса, которым я обычно следую (как на работе, так и для частных проектов, где я решаю), запрещают отдельные операторы без блока (т.е. каждый if / while / for нуждается в блоке).

0 голосов
/ 22 мая 2012

Вы также можете сделать одну строку, если затем оператор else, как это:

z = (x == y)? x*y : y-z;
0 голосов
/ 02 февраля 2009

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

0 голосов
/ 02 февраля 2009

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

Попробуйте заранее определить realOther как объект, а затем просто назначить realOther с помощью = (Square) other; / = (Прямоугольник) другое;

Местность - это ваша проблема.

...