Java: if-return-if-return vs if-return-elseif-return

随声附和 提交于 2019-12-03 04:26:12

The generated byte code is identical for those two cases, so it's purely a matter of style.

I produced two methods e1 and e2 and both produced this byte code (read using javap -v):

public boolean e1(java.lang.Object);
  Code:
   Stack=2, Locals=2, Args_size=2
   0:   aload_0
   1:   aload_1
   2:   if_acmpne   7
   5:   iconst_1
   6:   ireturn
   7:   aload_1
   8:   ifnonnull   13
   11:  iconst_0
   12:  ireturn
   13:  aload_0
   14:  invokevirtual   #25; //Method java/lang/Object.getClass:()Ljava/lang/Class;
   17:  aload_1
   18:  invokevirtual   #25; //Method java/lang/Object.getClass:()Ljava/lang/Class;
   21:  if_acmpeq   26
   24:  iconst_0
   25:  ireturn

I left out the code I put after that to make it compile.

Neither one is more efficient than the other. The compiler can easily see that the two are identical, and in fact Suns/Oracles javac produces identical bytecode for the two methods.

Here is an IfTest class:

class IfTest {

    public boolean eq1(Object obj) {
        if (this == obj)
            return true;

        if (obj == null)
            return false;

        if (getClass() != obj.getClass())
            return false;

        return true;
    }


    public boolean eq2(Object obj) {

        if (this == obj)
            return true;

        else if (obj == null)
            return false;

        else if (getClass() != obj.getClass())
            return false;

        return true;
    }
}

I compiled it with javac and the disassembly is as follows:

public boolean eq1(java.lang.Object);
  Code:
   0:   aload_0
   1:   aload_1
   2:   if_acmpne   7
   5:   iconst_1
   6:   ireturn
   7:   aload_1
   8:   ifnonnull   13
   11:  iconst_0
   12:  ireturn
   13:  aload_0
   14:  invokevirtual   #2; //Method Object.getClass:()Ljava/lang/Class;
   17:  aload_1
   18:  invokevirtual   #2; //Method Object.getClass:()Ljava/lang/Class;
   21:  if_acmpeq   26
   24:  iconst_0
   25:  ireturn
   26:  iconst_1
   27:  ireturn

 

public boolean eq2(java.lang.Object);
  Code:
   0:   aload_0
   1:   aload_1
   2:   if_acmpne   7
   5:   iconst_1
   6:   ireturn
   7:   aload_1
   8:   ifnonnull   13
   11:  iconst_0
   12:  ireturn
   13:  aload_0
   14:  invokevirtual   #2; //Method Object.getClass:()Ljava/lang/Class;
   17:  aload_1
   18:  invokevirtual   #2; //Method Object.getClass:()Ljava/lang/Class;
   21:  if_acmpeq   26
   24:  iconst_0
   25:  ireturn
   26:  iconst_1
   27:  ireturn

That is, I would recommend using the first version (without the else). Some people may argue that it's cleaner with the else parts, but I would argue the opposite. Including the else indicates that the programmer didn't realize that it was unnecessary.

I don't see any practical reason to replace one of those implementations with the other one - in any direction.

The second example would make sense if you wanted to avoid multiple return statements in one method - some people prefer that way of coding. Then we need the if-else if constructs:

public boolean equals(Object obj)
{
    boolean result = true;

    if (this == obj)
        result = true;

    else if (obj == null)
        result = false;

    else if (getClass() != obj.getClass())
        result = false;

    return result;
}

Think of it this way. When a return statement is executed, control leaves the method, so the else doesn't really add any value, unless you want to argue that it adds readability (which I don't really think it does, but others may disagree).

So when you have:

if (someCondition)
    return 42;

if (anotherCondition)
    return 43;

There's not really any value in adding an else to the second if.

In fact, I use a tool when writing C# code called Resharper, and it will actually mark the else as useless code in these situations. So I think that generally, it's better to leave them out. And as Joachim already mentioned, the compiler optimizes them away anyway.

I think this code can be improved a little (mind you, it is very readable):

  if (obj == null)
        return false;

  if (getClass() != obj.getClass())
        return false;

The instanceof operator is equivalent to both of those combined and is probably faster - less code, and no method invocations:

  if (!(obj instanceof MyClass))
        return false;

But what do I know.... I'm too lazy to analyze the byte code (having never done it before). :-p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!