Jak przekonwertować ślad stosu na ciąg?


1502

Jaki jest najłatwiejszy sposób przekonwertowania wyniku Throwable.getStackTrace()na ciąg znaków przedstawiający stacktrace?


6
Ponieważ odpowiedź jqno faktycznie używa metody Throwable.getStackTrace () określonej w pytaniu, podczas gdy Brian nie. Zamiast tego używa Throwable.printStackTrace ().
Stijn de Witt

10
Prawie każdy projekt Java powinien zawierać Apache commons-lang. Obejmuje wiele wygodnych metod realizujących niezwykle powszechne potrzeby programistyczne.
Russell Silva,

20
@StijndeWitt Te trzy linie kodu prawie na pewno wymagają faktoringu poza miejscem, w którym je nazwiesz. Ponieważ nie wiesz, gdzie je umieścić, trafią do Twojego zestawu narzędzi wraz ze wszystkimi innymi przydatnymi fragmentami. Bingo! właśnie wymyśliłeś guava / commons-lang / cokolwiek ... tylko nie tak dobrze. Zamiast tego zaimportuj rozsądną bibliotekę narzędzi i oszczędzaj na nowo wymyślając koło. Prawdziwym znakiem nowicjusza jest myślenie, że można wykonać lepszą robotę niż autorzy bibliotek.
Andrew Spencer

6
1. Guava ma - Throwables.getStackTraceAsString (e) 2. Apache Commons Lang - ExceptionUtils.getFullStackTrace 3. Napisz własne metody niestandardowe
user2323036

8
@AndrewSpencer Nie rozumiem, dlaczego tak bardzo staracie się obalić StijndeWitt za to, że chcecie to osiągnąć za pomocą małego fragmentu kodu. Naprawdę nie ma większego niebezpieczeństwa przy pisaniu drobnej metody użytkowej (nie uważam jej za „ARROGANIĘ O SZCZĘŚCIE, oh ​​nieeeee !! myśli, że jest lepszy niż Apache !!”). Istnieje mnóstwo projektów, zwłaszcza w językach JVM innych niż Java, które tak naprawdę nie chcą uwzględniać Guava ani Commons Lang tylko do rejestrowania stosu. Piszę biblioteki Scala i Clojure i na pewno nie uczynię Apache Commons Lang zależnością przechodnią tylko dla jednej metody.
jm0

Odpowiedzi:


1039

Można użyć następującej metody do konwersji Exceptionśledzenia stosu String. Ta klasa jest dostępna w Apache commons-lang, który jest najczęściej zależną biblioteką z wieloma popularnymi otwartymi źródłami

org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)


88
@Stijn - żeby być uczciwym (poniżej napisałem aktualnie najwyższą głosowaną odpowiedź), warto spojrzeć na commons-lang, aby uzyskać o wiele więcej funkcji
Brian Agnew

54
@StijndeWitt Commons Lang jest dość powszechny. Jest już obecny w większości moich projektów / proyectów w pracy.
WhyNotHugo

16
@Hugo dzięki, zamierzałem użyć StringWriter, aby uniknąć dodania nowej biblioteki - okazuje się, że jest to już zależność 3 moich zależności. Resztę sprawdź, czy już go masz.
Nathanial,

33
@MartinAsenov - zgodnie z logiką nigdy nie użyłbyś takiej biblioteki, prawda? Nie użyłbyś go, chyba że już go używasz?
Brian Agnew

16
FYI, pakiet został zmieniony i teraz klasa jest pod adresem: org.apache.commons.lang3.exception.ExceptionUtils.
schmmd

2201

Służy Throwable.printStackTrace(PrintWriter pw)do wysyłania śledzenia stosu do odpowiedniego programu piszącego.

import java.io.StringWriter;
import java.io.PrintWriter;

// ...

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); // stack trace as a string
System.out.println(sStackTrace);

505
Jeśli nie lubisz dołączać zewnętrznej biblioteki dla czegoś tak małego i prostego, jak to, skorzystaj z tej odpowiedzi.
Stijn de Witt

8
To przycina ślad stosu, tak samo jak printStackTrace (). Wszystkie wyjątki w stosie są widoczne, ale dla każdego wyjątku stos może zostać przycięty. Każdy, kto wymaga całego śladu, powinien to rozważyć.
Laila Agaev

5
Jak się okazuje, jest to właściwie dokładnie to, co robi metoda Apception ExceptionUtils.getStackTrace (). Właściwie prawie do litery.
ticktock

6
@BrianAgnew, nie powinieneś zamknąć StringWriteri PrintWriter?
Muhammad Gelbana

13
@BrianAgnew, dzięki za odpowiedź. To mnie zainteresowało i oto co znalazłem: stackoverflow.com/questions/14542535/...
Muhammad Gelbana

459

To powinno działać:

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();

69
Zwięzłe w kontekście java jest zawsze zachowana. Że printStackTracepowinien po prostu powrócić ciąg, pozostawiając decyzję, czy wydrukować go lub nie do użytkownika :)
Dmitry

35
printStackTrace drukowanie w konsoli jest dopuszczalne, ale przynajmniej getStackTrace zwracający go jako ciąg znaków powinien być domyślnie dostępny
Mateus Viccari,

5
Jaka część tego jest zwięzła? Musisz skonstruować 2 obiekty, które istnieją wyłącznie w celu umieszczenia śladu stosu w łańcuchu.
ArtOfWarfare

7
@dmitry Wywołana metoda printXXX()powinna wypisać XXX.
user207421,

2
@Greg Właściwie to nie był nawet sarkazm, wymagało jedynie prostego odczytania tego, co powiedział.
Andrew

224

Jeśli tworzysz dla Androida, znacznie łatwiejszym sposobem jest skorzystanie z tego:

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

Format jest taki sam jak getStacktrace, np

09-24 16:09:07.042: I/System.out(4844): java.lang.NullPointerException
09-24 16:09:07.042: I/System.out(4844):   at com.temp.ttscancel.MainActivity.onCreate(MainActivity.java:43)
09-24 16:09:07.042: I/System.out(4844):   at android.app.Activity.performCreate(Activity.java:5248)
09-24 16:09:07.043: I/System.out(4844):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.access$800(ActivityThread.java:139)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
09-24 16:09:07.043: I/System.out(4844):   at android.os.Handler.dispatchMessage(Handler.java:102)
09-24 16:09:07.043: I/System.out(4844):   at android.os.Looper.loop(Looper.java:136)
09-24 16:09:07.044: I/System.out(4844):   at android.app.ActivityThread.main(ActivityThread.java:5097)
09-24 16:09:07.044: I/System.out(4844):   at java.lang.reflect.Method.invokeNative(Native Method)
09-24 16:09:07.044: I/System.out(4844):   at java.lang.reflect.Method.invoke(Method.java:515)
09-24 16:09:07.044: I/System.out(4844):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
09-24 16:09:07.044: I/System.out(4844):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)

2
Dzięki. W takim przypadku data i znacznik nie są zapisywane w każdym wierszu, jak w printStackTrace ().
CoolMind

1
W rzeczywistości Log.getStackTraceString w swoim rdzeniu używa wspomnianego wyżej (D. Wróblewskiego) StringWriter i Printwriter.
MikeL

2
Najprostszym sposobem na wydrukowanie go w dzienniku systemu Android jest: Log.e("TAG", "My message", new Throwable());
Erick M. Sprengel


113

OSTRZEŻENIE: Nie zawiera przyczyny (która zwykle jest użytecznym bitem!)

public String stackTraceToString(Throwable e) {
    StringBuilder sb = new StringBuilder();
    for (StackTraceElement element : e.getStackTrace()) {
        sb.append(element.toString());
        sb.append("\n");
    }
    return sb.toString();
}

1
Wybrałbym rozszerzenie tego podejścia, jeśli chcesz przyciąć ślad, np. Przekazać parametr maxLines i dodać tylko tyle wierszy do śledzenia
Rich Seller

Brakuje nawiasów po e.getStackTrace. public static String stackTraceToString (wyjątek e) {StringBuilder sb = new StringBuilder (); for (element StackTraceElement: e.getStackTrace ()) {sb.append (element.toString ()); sb.append („<br />”); } return sb.toString (); }
rlc,

2
Nie jestem pewien, ale myślę, że to nie wydrukuje śladu stosu wyjątku przyczyny pierwotnej.
apoorv020

7
Cokolwiek robisz, nie przycinaj śladu. Zdarzyło mi się wiele, wiele razy, że patrzyłem na ślad stosu w dziennikach GlassFish, w którym usunięto przydatne części.
cayhorstmann

Użyj String.format("%n")lub coś podobnego zamiast, "\n"aby uszczęśliwić lamery DOS.
Ceving

89

Dla mnie najczystszym i najłatwiejszym sposobem było:

import java.util.Arrays;
Arrays.toString(e.getStackTrace());

37
Kod jest czysty, ale wynik nie. Na końcu musisz zrobić .replaceAll („,”, „\ n”). Jednak tracisz wcięcie, które proponuje printStackTrace.
furia

4
Jest to przydatne, gdy logujesz śledzenie w jednym wierszu
webjockey

28
public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}

1
Cześć, chciałbym tylko zaznaczyć, że w cytowanej części odpowiedzi w cytowanej odpowiedzi zaznaczono, że obiekty StringWriteri PrintWriterpowinny być closed .... (lub chyba tylko PrintWritertrzeba je zamknąć, ponieważ zamknięcie powinno również zamknąć StringWriter)
Eric

8
Przez inspirację masz na myśli skopiowane?
Stosujesz

26

Poniższy kod pozwala uzyskać cały stackTrace w Stringformacie bez użycia interfejsów API, takich jak log4J, a nawet java.util.Logger:

catch (Exception e) {
    StackTraceElement[] stack = e.getStackTrace();
    String exception = "";
    for (StackTraceElement s : stack) {
        exception = exception + s.toString() + "\n\t\t";
    }
    System.out.println(exception);
    // then you can send the exception string to a external file.
}

1
tak, ale to trochę nieporęczne, nie sądzisz? w rozsądnych ramach rejestrowania projektu jest koniecznością, więc po co się martwić
mzzzzb

Ten na początku nie wyświetla komunikatu o błędzie. można jednak dodać
kommradHomer

Możesz użyć StringBuffer zamiast prostej konkatenacji.
dedda1994

Jest to przydatne, gdy nie możesz zarejestrować wiadomości ze względu na prywatność.
A1m

Pamiętaj jednak, że to rozwiązanie nie rejestruje wewnętrznych przyczyn
A1m

19

Oto wersja, którą można skopiować bezpośrednio do kodu:

import java.io.StringWriter; 
import java.io.PrintWriter;

//Two lines of code to get the exception into a StringWriter
StringWriter sw = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(sw));

//And to actually print it
logger.info("Current stack trace is:\n" + sw.toString());

Lub w bloku catch

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}

będzie to dalej wykraczać poza zakres obecnej funkcji, tj. gdzie Throwablejest zdefiniowane, prawda?
n611x007

16
Arrays.toString(thrown.getStackTrace())

To najprostszy sposób na przekonwertowanie wyniku na ciąg. Używam tego w moim programie do drukowania śladu stosu

LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});

Pracował dla mnie, nic nie wygląda na przycinanie! Odpowiedź prostsza niż inna bez żadnej biblioteki zewnętrznej, świetna odpowiedź!
Shaung Cheng

16

Wydrukuj ślad stosu na a PrintStream, a następnie przekonwertuj go na String:

// ...

catch (Exception e)
{
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    e.printStackTrace(new PrintStream(out));
    String str = new String(out.toByteArray());

    System.out.println(str);
}

1
to jest najbardziej bezpośrednia odpowiedź
DaSqy Stc

11

Drukowanie śladu stosu na łańcuch

import java.io.PrintWriter;
import java.io.StringWriter;

public class StackTraceUtils {
    public static String stackTraceToString(StackTraceElement[] stackTrace) {
        StringWriter sw = new StringWriter();
        printStackTrace(stackTrace, new PrintWriter(sw));
        return sw.toString();
    }
    public static void printStackTrace(StackTraceElement[] stackTrace, PrintWriter pw) {
        for(StackTraceElement stackTraceEl : stackTrace) {
            pw.println(stackTraceEl);
        }
    }
}

Jest to przydatne, gdy chcesz wydrukować bieżący ślad stosu wątków bez tworzenia instancji Throwable- ale pamiętaj, że tworzenie nowego Throwablei uzyskiwanie śledzenia stosu z tego miejsca jest w rzeczywistości szybsze i tańsze niż wywołanie Thread.getStackTrace.


11

Kotlin

Rozszerzenie klasy Throwable da ci właściwość String error.stackTraceString:

val Throwable.stackTraceString: String
  get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    this.printStackTrace(pw)
    return sw.toString()
  }

10
private String getCurrentStackTraceString() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return Arrays.stream(stackTrace).map(StackTraceElement::toString)
            .collect(Collectors.joining("\n"));
}

1
Dziękuję eddyrkokr! Działa idealnie dla wszystkich moich klas. Właśnie dodałem go do podstawowej klasy TestNG i zbiera on stosy jeden po drugim ze wszystkich moich testów!
Krzysztof Walczewski

9

Sprytne strzelanie w pierwszy zestaw komentarzy było bardzo zabawne, ale tak naprawdę zależy od tego, co próbujesz zrobić. Jeśli nie masz jeszcze właściwej biblioteki, to 3 wiersze kodu (jak w odpowiedzi D. Wróblewskiego) są idealne. OTOH, jeśli masz już bibliotekę apache.commons (jak zrobi to większość dużych projektów), to odpowiedź Amara jest krótsza. OK, uzyskanie biblioteki i zainstalowanie jej może zająć dziesięć minut (mniej niż jedna, jeśli wiesz, co robisz). Ale zegar tyka, więc możesz nie mieć czasu do stracenia. Jarek Przygódzki miał ciekawe zastrzeżenie - „Jeśli nie potrzebujesz zagnieżdżonych wyjątków”.

Ale co, jeśli nie potrzebujemy pełnych ślady stosu, zagnieżdżone i wszystkich? W takim przypadku sekret polega na użyciu getFullStackTrace apache.common (patrz http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html # getFullStackTrace% 28java.lang.Throwable% 29 )

Uratowało mi to bekon. Dzięki, Amar, za podpowiedź!


9

Kod z Apache Commons Lang 3.4 ( JavaDoc ):

public static String getStackTrace(final Throwable throwable) {
    final StringWriter sw = new StringWriter();
    final PrintWriter pw = new PrintWriter(sw, true);
    throwable.printStackTrace(pw);
    return sw.getBuffer().toString();
}

Różnica w porównaniu z innymi odpowiedziami polega na tym, że używa autoFlush on PrintWriter.


8

Bez java.io.*tego można to zrobić w ten sposób.

String trace = e.toString() + "\n";                     

for (StackTraceElement e1 : e.getStackTrace()) {
    trace += "\t at " + e1.toString() + "\n";
}   

A potem tracezmienna przechowuje ślad stosu. Wyjście zawiera również przyczynę początkową, wyjście jest identyczne zprintStackTrace()

Przykład, printStackTrace()daje:

java.io.FileNotFoundException: / (Is a directory)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:270)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
    at Test.main(Test.java:9)

traceString posiada, gdy drukowanystdout

java.io.FileNotFoundException: / (Is a directory)
     at java.io.FileOutputStream.open0(Native Method)
     at java.io.FileOutputStream.open(FileOutputStream.java:270)
     at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
     at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
     at Test.main(Test.java:9)

5

Wersja Scala

def stackTraceToString(e: Exception): String = {
  import java.io.PrintWriter
  val sw = new StringWriter()
  e.printStackTrace(new PrintWriter(sw))
  sw.toString
}

5

jeśli używasz Java 8, spróbuj tego

Arrays.stream(e.getStackTrace())
                .map(s->s.toString())
                .collect(Collectors.joining("\n"));

kod getStackTrace()funkcji można znaleźć Throwable.javajako:

public StackTraceElement[] getStackTrace() {
    return getOurStackTrace().clone();
}

a dla StackTraceElementdostawców to toString()jako:

public String toString() {
    return getClassName() + "." + methodName +
        (isNativeMethod() ? "(Native Method)" :
         (fileName != null && lineNumber >= 0 ?
          "(" + fileName + ":" + lineNumber + ")" :
          (fileName != null ?  "("+fileName+")" : "(Unknown Source)")));
}

Po prostu dołącz do StackTraceElement„\ n”.


To rozwiązanie nie uwzględnia wcięcia zakładki śledzenia stosu, w przeciwnym razie działa świetnie!
krizajb

4

rozszerzenie odpowiedzi Gali, które obejmie również przyczyny wyjątku:

private String extrapolateStackTrace(Exception ex) {
    Throwable e = ex;
    String trace = e.toString() + "\n";
    for (StackTraceElement e1 : e.getStackTrace()) {
        trace += "\t at " + e1.toString() + "\n";
    }
    while (e.getCause() != null) {
        e = e.getCause();
        trace += "Cause by: " + e.toString() + "\n";
        for (StackTraceElement e1 : e.getStackTrace()) {
            trace += "\t at " + e1.toString() + "\n";
        }
    }
    return trace;
}

4

Rozwiązaniem jest konwersja stackTrace tablicy na ciąg danych typu. Zobacz następujący przykład:

import java.util.Arrays;

try{

}catch(Exception ex){
    String stack = Arrays.toString(ex.getStackTrace());
    System.out.println("stack "+ stack);
}

4

Z Java 8 Stream API możesz zrobić coś takiego:

Stream
    .of(throwable.getStackTrace())
    .map(StackTraceElement::toString)
    .collect(Collectors.joining("\n"));

Bierze tablicę elementów śledzenia stosu, konwertuje je na ciąg i łączy w ciąg wielowierszowy.


2
To rozwiązanie usuwa komunikat i ignoruje cały ślad nadrzędny
judovana

3

Mój oneliner do konwersji śledzenia stosu na dołączony ciąg wielu linii:

Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))

Łatwy do przekazania do rejestratora „jak jest”.


Dostajesz coś, co różni się od tego printStackTrace()tutaj, tracisz: 1) wyjątek, który został zgłoszony; 2) Przyczyny i ich śledzenie stosu
valijon

Różnicy można się spodziewać, ponieważ konwersja printStackTrace()nigdy nie była częścią pytania.
Andrey Lebedenko,

2

Jeśli nie chcesz korzystać z biblioteki zewnętrznej i nie tworzysz aplikacji dla systemu Android , możesz utworzyć metodę „rozszerzenia” w następujący sposób :

public static String getStackTraceString(Throwable e) {
    return getStackTraceString(e, "");
}

private static String getStackTraceString(Throwable e, String indent) {
    StringBuilder sb = new StringBuilder();
    sb.append(e.toString());
    sb.append("\n");

    StackTraceElement[] stack = e.getStackTrace();
    if (stack != null) {
        for (StackTraceElement stackTraceElement : stack) {
            sb.append(indent);
            sb.append("\tat ");
            sb.append(stackTraceElement.toString());
            sb.append("\n");
        }
    }

    Throwable[] suppressedExceptions = e.getSuppressed();
    // Print suppressed exceptions indented one level deeper.
    if (suppressedExceptions != null) {
        for (Throwable throwable : suppressedExceptions) {
            sb.append(indent);
            sb.append("\tSuppressed: ");
            sb.append(getStackTraceString(throwable, indent + "\t"));
        }
    }

    Throwable cause = e.getCause();
    if (cause != null) {
        sb.append(indent);
        sb.append("Caused by: ");
        sb.append(getStackTraceString(cause, indent));
    }

    return sb.toString();
}

2

Stare pytanie, ale chciałbym tylko dodać specjalny przypadek, w którym nie chcesz wydrukować całego stosu , usuwając niektóre części, które tak naprawdę nie są zainteresowane, z wyłączeniem niektórych klas lub pakietów.

Zamiast PrintWriterużycia SelectivePrintWriter:

// This filters out this package and up.
String packageNameToFilter = "org.springframework";

StringWriter sw = new StringWriter();
PrintWriter pw = new SelectivePrintWriter(sw, packageNameToFilter);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); 
System.out.println(sStackTrace);

Jeżeli SelectivePrintWriterklasę podaje:

public class SelectivePrintWriter extends PrintWriter {
    private boolean on = true;
    private static final String AT = "\tat";
    private String internal;

    public SelectivePrintWriter(Writer out, String packageOrClassName) {
        super(out);
        internal = "\tat " + packageOrClassName;
    }

    public void println(Object obj) {
        if (obj instanceof String) {
            String txt = (String) obj;
            if (!txt.startsWith(AT)) on = true;
            else if (txt.startsWith(internal)) on = false;
            if (on) super.println(txt);
        } else {
            super.println(obj);
        }
    }
}

Należy pamiętać, że tę klasę można łatwo dostosować do filtrowania według Regex containslub innych kryteriów. Pamiętaj też, że zależy to od Throwableszczegółów implementacji (prawdopodobnie nie ulegnie zmianie, ale nadal).


1
Tak, działa to dobrze i jest całkiem przydatnym pomysłem.
gil.fernandes

2
 import java.io.PrintWriter;
import java.io.StringWriter;

public class PrintStackTrace {

    public static void main(String[] args) {

        try {
            int division = 0 / 0;
        } catch (ArithmeticException e) {
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            System.out.println(exceptionAsString);
        }
    }
}

Po uruchomieniu programu wynik będzie podobny:

java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.java:9)

1

Zastanawiam się, dlaczego nikt nie wspomniał ExceptionUtils.getStackFrames(exception)

Dla mnie jest to najwygodniejszy sposób na zrzucenie stacktrace ze wszystkimi jego przyczynami do końca:

String.join("\n", ExceptionUtils.getStackFrames(exception));

0

Ostrzeżenie: to może być trochę nie na temat, ale no cóż ...;)

Nie wiem, jaki był pierwotny powód plakatów, że chciałem, aby ślad stosu był ciągiem. Kiedy ślad stosu powinien skończyć się w dzienniku SLF4J / Logback, ale nie było wyjątku ani nie należy go zgłaszać, oto co robię:

public void remove(List<String> ids) {
    if(ids == null || ids.isEmpty()) {
        LOG.warn(
            "An empty list (or null) was passed to {}.remove(List). " +
            "Clearly, this call is unneccessary, the caller should " + 
            "avoid making it. A stacktrace follows.", 
            getClass().getName(),
            new Throwable ("Stacktrace")
        );

        return;
    }

    // actual work, remove stuff
}

Podoba mi się, ponieważ nie wymaga biblioteki zewnętrznej (innej niż backend logowania, który i tak będzie przez większość czasu na miejscu).


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.