2013-03-15 13 views
10

Mam podklasę i nadklasę. W superklasie mam metodę, która rejestruje coś. Kiedy utworzę instancję podklasy, program rejestrujący tworzy komunikat rejestrowania dla super klasy. Dlaczego to się dzieje? PrzykłademJak uzyskać rejestrator dla podklasy?

Kod:

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"); 
    } 
} 

SubClass.java

public class SubClass extends SuperClass { 
} 

TestLogBubClass.java

public class TestLogBubClass { 

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

wyjściowa:

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

Jak widać nazwa klasy jest poprawnie wydrukowana, ale niepoprawnie reprezentowana w komunikacie dziennika.

Odpowiedz

5

Powód ten jest w JavaDoc dla LogRecord:

Zauważ, że jeśli aplikacja kliencka nie określił jednoznacznie nazwa metody źródło i źródło nazwę klasy, a następnie klasa LogRecord będzie wnioskować je automatycznie, gdy są one najpierw dostęp (ze względu na wywołanie getSourceMethodName lub getSourceClassName) przez analizę stosu wywołań.

Stos wywołań w tym przypadku kończy się w sposób zdefiniowany przez SuperClass, więc LogRecord zakłada, że ​​jest to klasa jest wywoływany. Jeśli chcesz zobaczyć to w akcji, wykonanie tego kodu:

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(); 
    } 
} 

Edit: Nie używam Jul, ale miał nadzieję, że nie będzie to łatwy sposób skonfigurować wyjście (jak każda inna realizacja rejestrator zapewnia). Wygląda na to, że musisz zaimplementować własną klasę Formatter i określić ją przy użyciu właściwości java.util.logging.ConsoleHandler.formatter.

Zalecam, jeśli to możliwe, przełączenie na SLF4J. Możesz połączyć wszystkie istniejące j.u.l kodu przez SLF4J do rzeczywistego rejestratora, który daje większą kontrolę nad jego wyjściami (jak Log4J lub Logback).

0

Myślę, że mam obejście, nawet jeśli nie mogę podać pełnego wyjaśnienia.

Zastępowanie logAndPrintClass z zaledwie super rozmowy, jak ta, w SubClass:

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

nadal mam ten sam wynik.

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

Potem po prostu skopiowane treści metody na podklasy:

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"); 
    } 
} 

Następnie mam innego wyjścia:

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

nie wiem dlaczego to działa, ale tylko Różnica wydaje mi się, że obiekt Logger jest teraz tworzony w podklasie zamiast wewnątrz superklasy.

+0

To jest tak, że obiekt 'LogRecord', który jest ukryty za wywołaniem' logger.log() 'jest tworzony w podklasie. – parsifal

+0

Nie chcę przesłonić metody w każdej podklasie ze względu na rejestrowanie. W kodzie produkcyjnym robi więcej niż tylko drukowanie i rejestrowanie wiadomości. Kod w pytaniu jest po prostu najprostszym przykładem, który ma takie samo zachowanie. – Paling

1

Ten kod java.util.logging jest dość dziwny .. Rejestrowanie nie korzysta z name, ale próbuje znaleźć samą klasę źródłową (która następnie jest rejestrowana). Zapoznaj się z metodą private void inferCaller() w klasie .

1

@Parsifal wyjaśnił, dlaczego tak się dzieje, spróbuję wyjaśnić obejście.

Jeśli chcesz zobaczyć dokładną klasę, w której metoda jest wywoływana, polecam używanie log4j lub slf4j. Jeśli potrzebujesz użyć java.util.Logger, to spójrz na jul-to-slf4j.

Próbowałem i dla mnie z tych samych klas wejściowe wygląda następująco w moim standardowym wyjściu:

podklasa

15 marca 2013 20:39:44 SuperClass logAndPrintClass

INFORMACJE: LogMessage

20: 39: 44478 INFORMACJE podklasy 12 - LogMessage

A w pliku dziennika jest tylko:

20: 39: 44.478 INFO podklasy: 12 - LogMessage

To może wyglądać nie tak dobre, ale w niektórych przypadkach może to być jako odpowiednie obejście.

Powiązane problemy