10

多くのファイル (約 5k) に System.out.println がある巨大な (古いレガシー Java) コードベースがあります。クリーンアップ/パフォーマンス上の理由から、それらを削除する予定です。コードに問題を発生させることなく、それらを置き換えるスクリプトをどのように作成できるでしょうか? 次のケースが問題になる可能性があるため、スクリプトはそれらを盲目的に削除することはできません。

if ()
  some.code...
else
  System.out.println(...);
DB.close();

それらを「;」に置き換えようと考えています。それは上記のケースを処理します。他に問題はありますか?他の提案はありますか?

4

8 に答える 8

26

ばかげたケースを考えましたか:

System.out.println(" Print " +  object.changeState() );

私はそれが起こるとは思わないが、println は、システムが依存するアクションを実際に実行しているメソッドを実行し、微妙なバグを引き起こす可能性がある (信じられないかもしれないが、私はこれを目撃した)

おそらく、ロガーに置き換えてロガーを無効にすることでうまくいくかもしれません。

または、NullObject パターンを使用して null オブジェクトを作成します。

public final class DevNull { 
    public final static PrintStream out = new PrintStream(new OutputStream() {
        public void close() {}
        public void flush() {}
        public void write(byte[] b) {}
        public void write(byte[] b, int off, int len) {}
        public void write(int b) {}

    } );
}

そして交換

 System.out.println();

 DevNull.out.println();
于 2009-02-21T03:58:18.900 に答える
12

Log4E は、"Replace System.out.println()" 機能を持つ Eclipse プラグインです。これらの厄介な println 呼び出しをすべて log4j 呼び出しに喜んで変換します。ログレベルチェックでそれらをラップすることさえあります。

于 2009-02-21T04:12:35.980 に答える
8

Oscarの概念を拡張すると、さらに優れたIMHOを実行できます。

if(!DEBUG) {
    System.setOut(
        new PrintStream(new OutputStream() {
            public  void    close() {}
            public  void    flush() {}
            public  void    write(byte[] b) {}
            public  void    write(byte[] b, int off, int len) {}
            public  void    write(int b) {}

        } );
    }
}

この場合、デバッグモードでない場合、またはその他のデフォルトのシステム出力が内部でdevNull実装に置き換えられている場合、それ以外の場合は期待どおりに機能します。このようにして、コード内の何かを見つけて置き換える必要はありません。

于 2009-02-21T10:09:17.603 に答える
6

Systems.setOut を呼び出し、何もしない独自の OutputStream を渡すことから始めることができます。これは、パフォーマンスの向上があるかどうかを確認するのに役立ちます。これはそれらを削除するよりも安全です (Oscar が指摘した理由により - 副作用によるコーディング)。パフォーマンスの向上が無視できる場合は、他の場所に集中することをお勧めします。

上記の方法に関する2つの問題:

  1. 保持したいSystem.out.printlnsも消えます
  2. 文字列の連結は引き続き行われます (その量によってはコストが高くなる可能性があります)。

ただし、探しているパフォーマンスの向上が得られるかどうかを確認するための良い簡単なテストです。

于 2009-02-21T04:14:22.713 に答える
4

条件付きコンパイルを使用して、印刷ステートメントを使用してデバッグ ビルドを作成し、印刷ステートメントを使用せずにリリース ビルドを作成できます。

基本的には、コンパイル時にスイッチとして使用する最終的な静的ブール値を持つ最終的な静的クラスを作成するという考え方です。

public final class Debug {
   //set to false to allow compiler to identify and eliminate
   //unreachable code
   public static final boolean ON = true;
}

System.out.println次に、すべてのステートメントを次のように置き換えることができます

if(Debug.ON)
{
    System.out.println...
}

コンパイラはコードの到達不能な分岐を無視するためON = false、リリース ビルドを実行するときに設定するだけで、print ステートメントがバイトコードから除外されます。

注:これはOscarが指摘した、print ステートメントがオブジェクトの状態を変更する可能性があるケースには対応していません。彼が提案したように、条件付きコンパイルを使用して、リリース モードのときに、出力を完全に削除する代わりに null オブジェクトに出力できます。

于 2009-02-21T04:09:47.110 に答える
1

個人的には{}代わりに使用しますが、同じように機能すると思います。

于 2009-02-21T03:45:40.020 に答える
0

これらのソースファイルを編集して行を削除することを検討しましたか?

開発者がそれらのほとんどを調べて取り除くのに数日しかかからないことに気付くかもしれません。同様の問題が発生しましたが、私は本当に早く起きて、ゴミを取り除くためにすべてのファイルを調べました。

Eclipseと保存時のクリーンアップ機能を使用して、インポートなどを同時にクリーンアップしました。

それはかなり治療的なことです!

于 2009-02-21T13:37:53.890 に答える
0

文字列「System.out.println」を「;//System.out.println」に置き換える正規表現を perl で作成しました。これによりビルドが壊れるケースはほとんどないと思います。これは、ゼロのバイトコード命令にコンパイルされる「else ;」になります。

これはあなたが提案したもののようです。同じ行に追加のステートメントがある場合を除いて、それは私にとってはうまくいきました。しかし、それはそもそも悪いスタイルです (そして、私はそれをしなかったことを知っていました)。

于 2009-02-21T08:41:26.097 に答える