11

先日、いくつかの Java コードを逆コンパイルしたところ、次のことがわかりました。

String s1 = "something";
String s2 = "something_else";

if (s1 == s2) {
// Path 1
} else {
// Path 2
}

明らかに「==」を使用して文字列が等しいかどうかをテストするのは悪いことです

しかし、私は疑問に思いました-このコードはコンパイルおよび逆コンパイルされています。すべての文字列がコンパイル時に定義され、インターンされ、コードがコンパイルされた場合、s1.equals(s2) が最適化されて「s1 == s2」になる可能性はありますか?

4

3 に答える 3

0

主なルールは、コンパイラが単一のクラスにあるソースコードから正確な値を差し引くことができる場合です。最小のコンパイル単位であるクラスのみを使用してすべての最適化を行うためです。コードを書くと

public class Test
{
    private static final String i = "1";
    public static void main(String[] args)
    {
        if(i == "2")
            System.out.println("hello");
        System.out.println("world");
    }
}

コンパイラは、このクラスのステートメントに関連するすべてのコードを確認し、if 条件を最適化します。逆コンパイラ後、コードは次のようになります

public class Test
{
  private static final String i = "1";

  public static void main(String[] paramArrayOfString)
  {
    System.out.println("world");
  }
}

(私はjd-guiを使用しました)

ただし、 で置き換える==.equals、コンパイラはメソッドがどのように機能するかを想定できません.equals。クラスのコンパイル後Test、JDK をハックして、 for を返すクラスの別のバージョンを配置できるためjava.lang.Stringです。true"1".equals("2")

したがって、コンパイラが実行できる最適化について考えるときは、まず、後でクラスを再コンパイルできる場合にコンパイラがどのように動作するかを考えてください。

別の例として、 がどのようenumに実装され、なぜそのような「奇妙な」方法が必要なのかを確認できます。

于 2013-04-11T21:09:42.423 に答える