Today I was at a Java interview and was dropped on an if .
The task was to write a method that returns the second largest number from the input array. It fell on the if when checking data. My implementation was:

 public int getSecondMaxNumber(int[] numbers) { if (numbers == null || numbers.length < 2) { throw new IllegalArgumentException(); } // далее логика получения второго макс. числа } 

To my great surprise, it turned out that I made a gross mistake. The program logic should be enclosed in an else block, that is, as follows:

 public int getSecondMaxNumber(int[] numbers) { if (numbers == null || numbers.length < 2) { throw new IllegalArgumentException(); } else { // именно здесь логика получения второго макс. числа } } 

Why do you need to write the rest of the code in the else block, if the flow of this method is interrupted while generating an exception?

Similarly, as it turned out, in the case when, instead of generating an exception, simply indicate return . And in general, after the if there should always be else .

As far as I understood from the words of the technical manager, in the case of the else JVM performs some optimization. I would like to know more about this point - what optimization and where can I read more about it?

  • 9
    As an option: they tested your confidence. They told you delirium, and you believed it. - Roman
  • one
    Honestly, I wouldn't even write brackets for this if (). - avp pm
  • 9
    About "some optimization" is nonsense. Probably someone from the side blurted out something, but they misunderstood. Themselves could not understand, because Nobody ever wrote compilers. I assure you that almost everywhere the bytecode of both examples will be identical, regardless of the language. Accordingly, there is no question of any additional optimization. - Sergey Rufanov
  • Guys, thank you all so much for the answers! Now I will know what happens at the interviews! - user184541
  • one
    @ AndreiKulik to find the 2nd number, these numbers must be at least two, but first it is checked that there are at least two numbers, otherwise an exception is thrown - Russtam

5 answers 5

In addition to the @VladD answer: I compiled the following class using java 8:

 public class IfElse { public int getSecondMaxNumber1(int[] numbers) { if (numbers == null || numbers.length < 2) { throw new IllegalArgumentException(); } return numbers[1]; } public int getSecondMaxNumber2(int[] numbers) { if (numbers == null || numbers.length < 2) { throw new IllegalArgumentException(); } else { return numbers[1]; } } } 

It can be seen that the bytecode methods are exactly the same:

 $ javap -c IfElse.class Compiled from "IfElse.java" public class IfElse { public IfElse(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public int getSecondMaxNumber1(int[]); Code: 0: aload_1 1: ifnull 10 4: aload_1 5: arraylength 6: iconst_2 7: if_icmpge 18 10: new #2 // class java/lang/IllegalArgumentException 13: dup 14: invokespecial #3 // Method java/lang/IllegalArgumentException."<init>":()V 17: athrow 18: aload_1 19: iconst_1 20: iaload 21: ireturn public int getSecondMaxNumber2(int[]); Code: 0: aload_1 1: ifnull 10 4: aload_1 5: arraylength 6: iconst_2 7: if_icmpge 18 10: new #2 // class java/lang/IllegalArgumentException 13: dup 14: invokespecial #3 // Method java/lang/IllegalArgumentException."<init>":()V 17: athrow 18: aload_1 19: iconst_1 20: iaload 21: ireturn } 

    No, nowhere is there any rule about mandatory else .

    On the contrary, for your particular case, the if form without else better, since it does not uselessly increase the nesting depth, but focuses attention on the fact that the code first checks the parameters and then runs as it is. In the proposed variant with the else code of the entire method would have an additional nesting depth due to the trivial verification at the beginning.

    Even if in the depths of JVM there would be an optimization that executes code with else rather, it would still be more correct to write differently than optimally (spending the time on the conditional nanosecond order operator, so you won’t win much), but how to understand . Poor optimization - the cause of all ills.

    Sit in a normal company, in this technical experts are no good.


    PS: Since the meaning of the code is that with else, that without the same, there are good chances that with the connected optimizations java will generate exactly the same intermediate code for both variants. Try it! (I don't have a java compiler at hand.)

      Rejoice that they did not get there. For example, there is no else in the jdk source.

      java.lang.Object#wait(long, int) from jdk 1.8 for example.

       public final void wait(long timeout, int nanos) throws InterruptedException { if (timeout < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && timeout == 0)) { timeout++; } wait(timeout); } 

        It seems to me that this is somehow related to the branch prediction mechanism. Suppose your function will be executed many, many times.

        Obviously, the code going in the else block will be executed an order of magnitude more often than the body of the if block.

        And based on this information, some optimizations can be performed, such as calling method calls in an else block, or loading your entire method into a higher-level loop. Or check altogether thrown out.

        But this is only my guesswork. Perhaps they heard something about it and tried to mislead their knowledge. And indeed nonsense to find fault with this at the interview.

        • 3
          Strange you have guesses. In a situation like this, with else, that without else - the compiler will generate exactly the same code. - Pavel Mayorov

        In your example, it only makes unnecessary trouble, think so

         public int getSecondMaxNumber(int[] numbers) { if (numbers == null || numbers.length < 2) { throw new IllegalArgumentException(); //если условие выполнится значит //вылетит исключение которое прервет эту функцию //а значит else тут будет лишним } // именно здесь логика получения второго макс. числа } 

        Take this example

         i = 1; if(i == 1){ //выполняем действие, но это действие не будет прерывать функцию } if(i == 2){ //получается джава будет сравнивать еще раз, не зависимо от того выполнилась ли i == 1 } //дабы джава не сравнивала еще раз обернем в else if(i == 1){ }else if(i == 2){ } 

        In such cases, use else.