10

サブクラスとスーパークラスがあります。スーパークラスには、何かを記録するメソッドがあります。サブクラスのインスタンスを作成すると、ロガーはスーパー クラスのログ メッセージを作成します。なぜこうなった?

コード例:

SuperClass.java

import java.util.logging.Level;
import java.util.logging.Logger;

public abstract class SuperClass {
    public void logAndPrintClass(){
        String name = this.getClass().getName();
        System.out.println(name);
        Logger logger = Logger.getLogger(name);
        logger.log(Level.INFO, "Logmessage");
    }
}

サブクラス.java

public class SubClass extends SuperClass {
}

TestLogBubClass.java

public class TestLogBubClass {

    public static void main(String[] args){
        SuperClass obj = new SubClass();
        obj.logAndPrintClass();
    }
}

出力:

SubClass
Mar 15, 2013 6:30:04 PM SuperClass logAndPrintClass
INFO: Logmessage

ご覧のとおり、クラスの名前は正しく出力されていますが、ログ メッセージでは正しく表示されていません。

4

4 に答える 4

5

この理由は、LogRecordの JavaDoc にあります。

クライアント アプリケーションで明示的なソース メソッド名とソース クラス名が指定されていない場合、LogRecord クラスは、(getSourceMethodName または getSourceClassName の呼び出しにより) 最初にアクセスされたときに、コール スタックを分析して自動的にそれらを推測します。

この場合、コール スタックは で定義されたメソッドで終了するSuperClassため、LogRecordはそれが呼び出されているクラスであると想定します。これを実際に見たい場合は、次のコードを実行します。

public class Example {

    public static class Superclass {
        public void foo() {
            new Exception().printStackTrace();
        }
    }

    public static class Subclass extends Superclass {
        // nothing here
    }

    public static void main(String[] argv)
    throws Exception
    {
        Superclass s = new Subclass();
        s.foo();
    }
}

編集: 私は jul を使用しませんが、(他のすべてのロガー実装が提供するように) 出力を構成する簡単な方法があることを望んでいました。独自のFormatterクラスを実装し、java.util.logging.ConsoleHandler.formatterプロパティを使用して指定する必要があるようです。

可能であれば、SLF4J に切り替えることをお勧めします。SLF4Jを介して既存のすべてのjulコードを実際のロガーにブリッジして、その出力をより詳細に制御できます(Log4JやLogbackなど)。

于 2013-03-15T18:31:09.560 に答える
1

@Parsifal は、これが発生する理由を説明しました。回避策を説明します。

メソッドが呼び出されている正確なクラスを確認したい場合は、log4jまたはslf4jを使用することをお勧めします。を使用する必要がある場合はjava.util.Loggerjul-to-slf4j をご覧ください。

私は試してみましたが、同じクラスの入力を使用すると、標準出力で次のようになります。

サブクラス

2013 年 3 月 15 日午後 8 時 39 分 44 秒 SuperClass logAndPrintClass

INFO: ログメッセージ

20:39:44,478 INFO サブクラス:12 - ログメッセージ

そして、ログファイルには次のものしかありません:

20:39:44,478 INFO サブクラス:12 - ログメッセージ

あまり良くないように見えるかもしれませんが、場合によってはこれが適切な回避策になるかもしれません。

于 2013-03-15T18:44:37.573 に答える
1

このjava.util.loggingコードはかなり奇妙です。ロギングは を使用しませんnameが、ソースクラス自体を見つけようとします (ログに記録されます)。private void inferCaller()classのメソッドを調べてくださいjava.util.logging.LogRecord

于 2013-03-15T18:37:19.030 に答える
0

完全な説明ができなくても、回避策があると思います。

次のように、呼び出しlogAndPrintClassだけで をオーバーライドします。superSubClass

class SubClass extends SuperClass {
    protected void logAndPrintClass(){ super.logAndPrintClass(); }
}

私はまだ同じ出力を得ました。

SubClass
Mar 15, 2013 11:22:10 AM SuperClass logAndPrintClass
INFO: Logmessage

次に、メソッド本体をサブクラスに単純にコピーしました。

class SubClass extends SuperClass {
    protected void logAndPrintClass(){
        String name = this.getClass().getName();
        System.out.println(name);
        Logger logger = Logger.getLogger(name);
        logger.log(Level.INFO, "Logmessage");
    }
}

それから私は別の出力を得ました:

SubClass
Mar 15, 2013 11:23:31 AM SubClass logAndPrintClass

なぜこれが機能するのかはわかりませんが、私が見つけた唯一の違いは、Loggerオブジェクトがスーパークラス内ではなくサブクラス内でインスタンス化されていることです。

于 2013-03-15T18:28:38.007 に答える