views:

3495

answers:

12

Is it possible to have IF statements without braces in Java, e.g:

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

It's possible in PHP, and I'm not sure if I'm doing something wrong.

Clarification: Here's my actual code that i'm using:

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

But i got errors like "Syntax token on realOther , delete this token" and "realOther cannot be resolved" among others.

What am I doing wrong?

+12  A: 

Yes, you can follow an if statement with a single statement without using curly braces (but do you really want to?), but your problem is more subtle. Try changing:

if (x=y)

to:

if (x==y)

Some languages (like PHP, for example) treat any non-zero value as true and zero (or NULL, null, nil, whatever) as false, so assignment operations in conditionals work. Java only allows boolean expressions (expressions that return or evaluate to a boolean) inside conditional statements. You're seeing this error because the result of (x=y) is the value of y, not true or false.

You can see this in action with this simple example:

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

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

The first statement will cause compilation to fail because 1 cannot be converted to a boolean.

Edit: My guess on your updated example (which you should have put in the question and not as a new answer) is that you are trying to access realOther after you assign it in those statements. This will not work as the scope of realOther is limited to the if/else statement. You need to either move the declaration of realOther above your if statement (which would be useless in this case), or put more logic in your if statement):

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

To assist further we would need to see more of your actual code.

Edit: Using the following code results in the same errors you are seeing (compiling with 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");
    }
}

Note that adding curly braces to that if/else statement reduces the error to a warning about unused variables. Our own mmyers points out:

http://java.sun.com/docs/books/jls/third_edition/html/statements.html says: "Every local variable declaration statement is immediately contained by a block." The ones in the if statement don't have braces around them, therefore they aren't in a block.

Also note that my other example:

((Square) other).doSomething()

compiles without error.

Edit: But I think we have established (while this is an interesting dive into obscure edge cases) that whatever you are trying to do, you are not doing it correctly. So what are you actually trying to do?

Sean Bright
Actually you can use = in if, you just have to use the result of that as a boolean expression, for example int i; if(i=1==1) { loopForever(); } This is awfully bad practice though, naturally.
Esko
Re "some part of the Java standard": http://java.sun.com/docs/books/jls/third_edition/html/statements.html says: "Every local variable declaration statement is immediately contained by a block." The ones in the for statement don't have braces around them, therefore they aren't in a block.
Michael Myers
Thanks! I've edited to take this into account.
Sean Bright
A: 

Yes, but you need to keep the semi colon between the if-else, like so:

if (true) System.out.println("true"); else System.out.println("false");

Also, make sure you fix your comparison operator to be ==.

Yuval A
+4  A: 

The following code is legal:

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

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

As Sean Bright mentioned, your problem is that you are trying to test a non-boolean expression. You should be using the == operator instead of the = operator in your if clause.

Another thing to mention is that it is considered, by many, bad practice to skip using the curly braces in an if-then-else statement. It can lead to errors down the road, such as adding another statement to the body of the if or else code blocks. It's the type of bug that might be a pain to figure out.

This isn't really an issue when using an if-else statement, because Java will catch this as a syntactic error (else statement without a preceding if). However, consider the following if statement:

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

Now, suppose later on you need to do more things if x == y. You could easily do the following without realizing the error.

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

Of course, the second statement w = x * y - 5 will be executed regardless of the outcome of the if statement test. If you had curly braces to begin with, you would have avoided the problem.

if (x == y) {
  z = y * x;
  w = x * y - 5; // this is obviously inside the if statement now
}
William Brendel
+2  A: 

It is possible (apart from the typo/bug that @Sean pointed out), but depending on the code guidelines you follow it's considered bad form.

The code guidelines that I usually follow (both at work and for private projects where I decide) forbids single statements without a block (i.e. every if/while/for needs a block).

Joachim Sauer
+1  A: 

Just because you can do something doesn't mean you should.

Consider what happens when you add logging:

if (x==y)
   z=x*y;
else
  System.out.println("Values weren't equal);
  z=y-x;

Surprise! "z" will never equal x * y. While you may think that leaving the brackets out makes your code more readable, it makes it much less safe. I only say this because I've had to troubleshoot tons of code that has this same defect.

Todd R
never ONCE have I seen anyone make this mistake if the statement was trivial and indentation was proper. NEVER. This prohibition is an overreaction to a non problem. (Okay, I'm done ranting.)
Kip
Same here. This ranks up there with 'final' in a parameter or local variable, multiple 'return' in a method, curly brace on newline ... and various other religious debates as to what some consider "proper" coding style.
Robin
+3  A: 

Always consult the Code Conventions for the JavaTM Programming Language:

Specifically, see Chapter 7, Section 4:

Note: if statements always use braces {}. Avoid the following error-prone form:

if (condition) //AVOID! THIS OMITS THE BRACES {}!
    statement;
eleven81
I hate this prohibition, personally. I have been coding for 9 years now, and never ONCE have I seen a problem resulting from omission of braces for trival if's, except in the case where indentation is not proper (in which case I've seen problems arise with or without braces).
Kip
I think this is true, if you following the true java code conventions it only takes up one extra line and makes it very nice to read, which is one of the most important things.
Mark Davidson
I agree with Kip, never seen this as a problem and I find it more readable without the braces. There is no 'true' convention, there are many, usually defined by the developers that started writing any given codebase to which they have been applied. Many of which are fodder for religious debates.
Robin
+1  A: 

If you want a one liner if that is an expression you can use the terniary operator

  final int myVal = predicate ? consequent : alternative;

which is roughly the same as

  final int myVal;
  if(predicate)
    myVal = consequent;
  else
    myVal = alternative;
John Nilsson
A: 

I always use braces because some languages allow them and some don't, and I can never keep them straight. Maybe I'm too old, or maybe I know too many languages.

Paul Tomblin
+3  A: 

Edit: To be more clear, this is your problem:

This:

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

is the exact same thing as this:

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

Notice that you never do anything with realOther. You define it there, but since it's scoped to that set of braces, you throw it away as soon as hitting the closing brace.

Not including the braces doesn't help, the fact that it's a statement (after an if) makes it an independent code block, as soon as that block exits, "realOther" is discarded.

Java recognizes that this is the case and tells you (To sloppily quote Inigo Montoya) "I don't think that means what you think it means" .

Secondary problem, Java is strongly typed. Even if it might allow syntax like you are saying, right after this if statement, it has to have an absolute final type for realOther. Your if statement would completely break java's brain because it wouldn't know if realOther was supposed to be treated as a rectangle or a square.

Suppose rectangle had a setWidth and setHeight method (and square just had a setHeight). After this IF statement, should Java allow you to call setWidth or not? Java MUST know these things at compile time (if not, we wouldn't need casting).

another edit:

To fix it, you use this:

// 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);
}

In other words, the way you're supposed to work with related objects is to leave them as the more abstract object for as long as possible, only using the specific objects when you need to call a method on that object.

If you code it right, you can almost always use the more abstract and rarely use the specific. With square and rect, this isn't obvious, square/rect is a pretty sloppy problem and is used as an example of some tough decisions you have to make with OO programming, but it really does work out nearly all the time--I very rarely have to cast at all...

Bill K
A: 

I must agree with Bill K... "You cannot say "Square realOther" in an if statement because you are declaring it within the scope of that single line of code, it would vanish at the end of the if statement."

Consider defining realOther beforehand as an Object, then simply assigning realOther with the = (Square) other; / = (Rectangle) other;

Locality is your problem, though.

Zachery Delafosse
+1  A: 

Is your code something like this?

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

//...

realOther.doSomething();

The problem is that in Java, unlike PHP, realOther does not exist outside the if statement. What is the type of other? Is it Object? If so, is there a common base class or interface to Square and Rectangle? (Shape maybe?) If so, you should do something more like this:

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

//...

if(realOther != null)
  realOther.doSomething();
Kip
A: 

Get your code to work with the braces, and then remove them. If you are learning something new, you should do one thing at a time.

Albert