10

In Javascript world (especially in React apps) I've seen expressions like [2]. However, in Java this is not so popular.

1.

if(isValid) {
   statement();
}
isValid && statement();

The outcome of [1] and [2] is identical as the statement() is not going to be evaluated if isValid == false.

  • Why syntax like [2] not popular? I mean, I literally never encounter this before in any Java project I've seen.
  • Are there any implications of approach [2]?
  • Is it considered to be harmful?
  • Are there any surprises I might come along using this as the alternative for simple if statements?
  • Does it decrease readability?

Edit:

I was testing this in Groovy console. I guess it invalidates this question quite much. Thanks for your responses anyways.

Grzegorz Gajos
  • 2,253
  • 19
  • 26
  • 3
    Well, the Java language doesn't support it. *Why* it doesn't support it is *opinion-based* ;-) – P.P Jul 22 '16 at 10:57
  • 3
    I don't understand the upvotes here. If it go re-tagged to Groovy I may remove my downvote - but I'm a bit disappointed by the question that a decade of Java experience produced. – Spork Jul 22 '16 at 11:45
  • In my view parameter-less void methods are good if you write your code to tell a story. Otherwise I highly recommend you take time to follow OOP principles and benefit from rigid design patterns :) – Palcente Jul 22 '16 at 12:25
  • 1
    `does it decrease readability?` - yes! Out of `isValid && a()` and `isValid || a` which one does do what again? You have to think how short-circuiting works - while if is natural language `if A then B` - couldn't get any more natural and readable than this! - why waste all this effort ? – Falco Jul 22 '16 at 12:58

3 Answers3

21

if( isValid && statement() ) only works if statement() returns a boolean otherwise the condition wouldn't be compilable. Doing that might not be considered good design (depends on what statement actually does) and might reduce readability or your ability to use the return value of statement().

Besides that just isValid && statement(); isn't supported by the language - and don't make the mistake to compare a language like Java to a language like JavaScript, they follow different paradigms.

You could do something like boolean b = isValid && statement(); but you'd normally only do that if you want to use the value of b somehow.

Edit: As requested by KRyan I'll also add a paragraph on the meaning of a && b and what it is used for in Java as well as JavaScript (although I'm no expert here).

Java

In general you can combine two boolean expressions using & (and) or | (or). Thus true & true will result in true as does true | false, but true & false will result in falseetc.

The problem with the single character operators is that every argument is evaluated even if you already know the result. As an example when you see false & ... you already know that the result is false when looking at the first argument and any other arguments won't make a difference.

Now if you have an expression that calls some methods which return a boolean value you might not want to execute those methods if they aren't needed, e.g. when the methods themselves are quite expensive. As an example consider needsCheckWebsite & isValueOnWebsite( "test" ). isValueOnWebsite( "test" ) might take a while and if needsCheckWebsite was false you'd not want to execute that method.

To fix that you can use the double-character operators && and ||, aka short-circuit operators. That means that if you write needsCheckWebsite && isValueOnWebsite( "test" ) and if needsCheckWebsite is false, the expensive execution of isValueOnWebsite( "test" ) won't happen since we already know that the result doesn't change a thing.

Hence isValid && statement() would mean that statement() should only be executed if isValid.

JavaScript

AFAIK in JavaScript the short-circuit operators work in a similar way in that it evaluates the first argument and if the result is still unknown the second argument is evaluated and returned. However, since JavaScript is a dynamically typed language (in constrast to Java which is statically typed) you can mix different types, e.g. var value = null || "hello" which would result in value = "hello".

This allows the developer to use && and || for things other than boolean logic, like supplying a default value, which is not possible in Java due to the static typing (in Java you could use the ternary operator ? for that, e.g. String s = input != null ? input : defaultValue but as you can see that doesn't look as elegant as JavaScript's var s = input || defaultValue).

Community
  • 1
  • 1
Thomas
  • 87,414
  • 12
  • 119
  • 157
  • Ahh, you are right. I was using this in `Groovy` actually. That's valid point. – Grzegorz Gajos Jul 22 '16 at 10:59
  • I could actually ask this question again asking about `Groovy` but I don't care about `Groovy` that much ;) – Grzegorz Gajos Jul 22 '16 at 11:08
  • @GrzegorzGajos hmm, I don't know Groovy that well but if it doesn't support that one reason might be that it is related to Java. There probably are some other reasons behind such a decision, technical ones as well as political/style related ones. – Thomas Jul 22 '16 at 11:11
  • In `Groovy` it will work well as it automatically map any result into boolean value. You can do `true && f()` even if `void f()`. – Grzegorz Gajos Jul 22 '16 at 11:14
  • 1
    @GrzegorzGajos ok in that case it's probably more a question of readability, i.e. `if( condition) { doSomething(); }` is easier to understand and less error prone than `condition && doSomething();`, i.e. you don't have to care about what `&&` does and don't have to worry about accidentially reordering the statement or just using `&`. – Thomas Jul 22 '16 at 11:19
  • 2
    @Thomas No, it's not easier and less error prone. It's exactly as easy and as error prone, or more specifically - it's opinion based. In other programming languages, I use both constructs; their meaning is a bit different to me, but outcome is the same. I use both and like them both. Depends on the language and the reader, but there are many cases where if would be less readable than and-ing. – MatthewRock Jul 22 '16 at 11:50
  • Maybe it is better code if you either pick one of either method calls or variables. I would use a variable in this example instead of statement() and carefully pick a name to inform the reader why validity isn't enough for the condition to hold true. I prefer variables when I have to evaluate a condition like this to make sure the condition is understandable and trust/not care about the compiler/runtime system to produce something efficient from it. – Anders Lindén Jul 22 '16 at 13:48
  • This answer would be much better if explained how `&&` works in JavaScript and *why* this construction makes sense in that language where it wouldn’t in Java. – KRyan Jul 22 '16 at 14:25
  • @KRyan I would but I'm not JavaScript expert so I answer the Java-related question only :) - If you want to add the JavaScript part (maybe there's a link) I could add that to the answer. – Thomas Jul 22 '16 at 14:44
  • In JavaScript, `A && B` returns `A` if `A` is falsey, and otherwise returns `B`. It has short-circuiting execution, so if `A` is falsey, `B` is never evaluated. The result is that `A && B` means `if A is falsey then A else B` more than it means proper boolean `and`. It works out the same as `and` in boolean contexts (since the truthy-or-falsey value of `B` is equivalent to the truthy-or-falsey value of `A && B` when `A` is truthy). For docs, [here are MDN’s on logical operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Logical_operators). – KRyan Jul 22 '16 at 14:52
  • @KRyan ok that's the same as in Java so I'll add short description on the short-circuit operator. – Thomas Jul 22 '16 at 15:12
  • It is **not** the same as in Java. Java always returns `true` or `false`. JavaScript always returns `A` or `B`. It evaluates the same in a boolean context, but JavaScript allows this construction to be used in non-boolean contexts, like `var value = valueMaybeNull || valueDefault;` where `value` becomes `valueMaybeNull` unless that value *is* `null`, in which case `value` becomes `valueDefault`. In Java, `value` would have to be a boolean value, not whatever values `valueMaybeNull` and `valueDefault` have. – KRyan Jul 22 '16 at 15:18
  • @KRyan I added the edit, please check whether I understood you correctly and if not suggest an edit :) Thx. – Thomas Jul 22 '16 at 15:35
  • It looks accurate, but I would expand on the JavaScript section. Something like "This allows JavaScript to use `&&` and `||` for things other than boolean logic, like supplying a default value, that Java's type-checker would not allow. So this approach isn't popular in Java because it's not allowed in Java unless you're already dealing with boolean values." – KRyan Jul 22 '16 at 15:36
  • @KRyan I added the first part and adjusted the second :) – Thomas Jul 22 '16 at 15:41
  • Excellent, looks great. – KRyan Jul 22 '16 at 15:44
8

They are not interchangeable:

isValid && statement(); is an expression and not a statement. Also it would only work when your statement() method is of type boolean .

So you could only use this where an (predicate) expression is expected by the Java-language syntax.

opinion: If you would use it when meeting the above requirements, then i would indeed find that it "Does decrease readability". (as it can only be used in certain situations, plus by your own words ("doing Java development for an almost decade now and I've never seen") nobody is expecting it)

raphaëλ
  • 6,393
  • 2
  • 29
  • 35
0

As it is explained in the previous answer, `isValid && statement(); is an expression and needs to be stored in some variable we can not directly use as it is.. but for the statement is not.

one more heap space occupied by using the expressions.

PrabaharanKathiresan
  • 1,099
  • 2
  • 17
  • 32