Как я могу преобразовать трассировку стека в строку?

1353

Каков самый простой способ преобразовать результат Throwable.getStackTrace() в строку, изображающую stacktrace?

  • 6
    Потому что в ответе jqno фактически используется метод Throwable.getStackTrace (), который вы указали в своем вопросе, а Брайан - нет. Вместо этого он использует Throwable.printStackTrace ().
  • 10
    Почти каждый Java-проект должен включать Apache commons-lang. Он включает в себя множество удобных методов, реализующих чрезвычайно распространенные потребности разработки.
Показать ещё 10 комментариев
Теги:
stack-trace
tostring

29 ответов

943
Лучший ответ

Для преобразования трассировки стека Exception в String можно использовать следующий метод. Этот класс доступен в Apache commons-lang, который является наиболее распространенной зависимой библиотекой со многими популярными открытыми источниками.

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

  • 1
    Ссылка для обновленной версии 3.0.1: commons.apache.org/lang/api-3.0.1/org/apache/commons/lang3/…
  • 373
    Одна строка, которая нуждается во внешней библиотеке ...
Показать ещё 13 комментариев
2094

Используйте Throwable.printStackTrace(PrintWriter pw), чтобы отправить трассировку стека соответствующему автору.

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);
  • 473
    Если вам не нравится включать внешнюю библиотеку для чего-то столь же маленького и простого, как этот, используйте этот ответ.
  • 7
    Это обрезает трассировку стека, так же, как printStackTrace (). Все исключения в стеке видны, но для каждого исключения стек может быть обрезан. Любой, кому требуется полный след, должен рассмотреть это.
Показать ещё 10 комментариев
420

Это должно работать:

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
  • 57
    Краткий в контексте Java всегда хиллярный. Этот printStackTrace должен просто возвращать строку, оставляя решение о том, печатать его пользователю или нет :)
  • 27
    printStackTrace печать в консоли допустима, но по крайней мере getStackTrace, возвращающий ее в виде строки, должен быть доступен по умолчанию
Показать ещё 4 комментария
198

Если вы разрабатываете Android, гораздо проще использовать это:

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

Формат такой же, как getStacktrace, например,

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
    Благодарю. В этом случае дата и тег записываются не в каждой строке, как в printStackTrace ().
  • 1
    На самом деле Log.getStackTraceString в своем ядре использует вышеупомянутые (D. Wroblewski's) StringWriter и Printwriter.
Показать ещё 1 комментарий
110

ПРЕДУПРЕЖДЕНИЕ: не включает причину (обычно это полезный бит!)

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
    Я бы пошел с расширением этого подхода, если вы хотите обрезать трассировку, например, передать параметр maxLines и добавить только столько строк в трассировку
  • 0
    Скобки после e.getStackTrace отсутствуют. public static String stackTraceToString (исключение e) {StringBuilder sb = new StringBuilder (); for (элемент StackTraceElement: e.getStackTrace ()) {sb.append (element.toString ()); sb.append ("<br />"); } return sb.toString (); }
Показать ещё 4 комментария
102

Guava Throwables класс

Если у вас есть фактический экземпляр Throwable, Google Guava предоставляет Throwables.getStackTraceAsString().

Пример:

String s = Throwables.getStackTraceAsString ( myException ) ;
83

Для меня самый чистый и простой способ:

import java.util.Arrays;
Arrays.toString(e.getStackTrace());
  • 33
    Код чистый, но на выходе нет. Вы должны сделать .replaceAll (",", "\ n") в конце. Однако вы теряете отступ, который предлагает printStackTrace.
  • 4
    Это полезно, когда вы регистрируете трассировку в одну строку
27
public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}
  • 1
    Привет, я просто хотел бы отметить, что в разделе комментариев цитируемого ответа указывается, что объекты StringWriter и PrintWriter должны быть close d .... (или я думаю, что только PrintWriter должен быть закрыт, так как его закрытие должно закройте StringWriter тоже)
  • 7
    Под вдохновением ты имеешь ввиду скопированный? Вы только поместите это в метод ... Чтение ответов здесь похоже на просмотр "Дня Сурка"
24

Следующий код позволяет вам получить весь стекTrace с форматом String без использования API, таких как log4J или даже 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.
}
  • 0
    да, но это немного громоздко, не правда ли? в любом разумном размере каркаса проекта является обязательным, поэтому зачем
  • 0
    Этот не дает сообщение об ошибке в начале. можно добавить хотя
Показать ещё 1 комментарий
19

Вот версия, скопированная непосредственно в код:

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

Или в блоке catch

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}
  • 0
    это будет продолжаться за пределами текущей функции, т.е. где Throwable определяется, верно?
  • 1
    Это самый близкий к правильному ответу.
11

Распечатать трассировку стека в PrintStream, а затем преобразовать его в строку

// ...

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

    System.out.println(str);
}
11

Печать трассировки стека в строку

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

Это полезно, когда вы хотите распечатать текущую трассировку стека потоков без создания экземпляра Throwable - но обратите внимание, что создание новой Throwable и получение трассировки стека оттуда происходит быстрее и дешевле, чем вызов Thread.getStackTrace.

10
Arrays.toString(thrown.getStackTrace())

Это самый простой способ преобразовать результат в строку, которую я использую в своей программе для печати трассировки стека

LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
10
private String getCurrentStackTraceString() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return Arrays.stream(stackTrace).map(StackTraceElement::toString)
            .collect(Collectors.joining("\n"));
}
  • 1
    Спасибо, eddyrkokr! Это прекрасно работает для всех моих предложений. Я только что добавил его в базовый класс TestNG, и он собирает трассировки стека по одному из всех моих тестов!
9

Котлин

Расширение класса Throwable даст вам свойство String error.stackTraceString:

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

Код из 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();
}

Разница с другими ответами заключается в том, что он использует autoFlush на PrintWriter.

8

Умный отстрел в первом наборе комментариев был очень забавным, но это действительно зависит от того, что вы пытаетесь сделать. Если у вас еще нет правильной библиотеки, то 3 строки кода (как в ответе Д. Вроблевского) идеальны. OTOH, если у вас уже есть библиотека apache.commons (как большинство крупных проектов), то ответ Amar короче. ОК, вам может потребоваться десять минут, чтобы получить библиотеку и установить ее правильно (меньше, чем один, если вы знаете, что делаете). Но часы тикают, поэтому у вас может не быть свободного времени. У Ярека Пшигодзки было интересное caveat-- "Если вам не нужны вложенные исключения".

Но что, если мне нужны полные трассировки стека, вложенные и все? В этом случае, секрет заключается в использовании apache.common getFullStackTrace (см http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html # getFullStackTrace% 28java.lang.Throwable% 29)

Это спасло мой бекон. Спасибо, Амар, за подсказку!

6

Без java.io.* это можно сделать следующим образом.

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

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

И затем переменная trace содержит вашу трассировку стека. Выход также содержит начальную причину, выход идентичен printStackTrace()

Пример, printStackTrace() дает:

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)

Строка trace имеет значение, если она напечатана на stdout

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)
4

если вы используете Java 8, попробуйте это

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

Вы можете найти код для функции getStackTrace(), предоставляемой Throwable.java:

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

а для StackTraceElement он предоставляет toString как:

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

Так что просто присоединитесь к StackTraceElement с помощью \n

  • 0
    Это решение не учитывает отступ вкладки трассировки стека, в противном случае он работает отлично!
4

exapansion на гала-ответе, который также будет включать причины исключения:

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;
}
3

Решением является преобразование stackTrace массива в строковый тип данных. Смотрите следующий пример:

import java.util.Arrays;

try{

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

Мой oneliner для преобразования трассировки стека во вложенную многострочную строку:

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

Легко перейти на регистратор "как есть".

  • 0
    Вы получаете что-то, что отличается от printStackTrace() Здесь вы потеряете: 1) Исключение, которое было сгенерировано; 2) Причины и их следы
  • 0
    Разница вполне ожидаемая, так как преобразование printStackTrace() никогда не было частью вопроса.
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);
        }
    }
}

Когда вы запустите программу, результат будет примерно таким:

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

Старый вопрос, но я просто хотел бы добавить специальный случай, когда вы не хотите печатать весь стек, удалив некоторые части, которые вас фактически не интересуют, исключая определенные классы или пакеты.

Вместо PrintWriter используйте 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);

Где класс SelectivePrintWriter задается:

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

Обратите внимание, что этот класс может быть легко адаптирован для фильтрации с помощью Regex, contains или других критериев. Также обратите внимание, что это зависит от деталей реализации Throwable (вряд ли изменится, но все же).

  • 1
    Да, это работает хорошо и на самом деле довольно полезная идея.
2

Если вы не хотите использовать внешнюю библиотеку и не разрабатываете для Android, вы можете создать 'extension следующим образом:

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

Я написал несколько методов для этого некоторое время назад, поэтому я решил, почему бы не бросить мои два цента на это.

/** @param stackTraceElements The elements to convert
 * @return The resulting string */
public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements) {
    return stackTraceElementsToStr(stackTraceElements, "\n");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @return The resulting string */
public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements, String lineSeparator) {
    return stackTraceElementsToStr(stackTraceElements, lineSeparator, "");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting string */
public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements, String lineSeparator, String padding) {
    String str = "";
    if(stackTraceElements != null) {
        for(StackTraceElement stackTrace : stackTraceElements) {
            str += padding + (!stackTrace.toString().startsWith("Caused By") ? "\tat " : "") + stackTrace.toString() + lineSeparator;
        }
    }
    return str;
}

/** @param stackTraceElements The elements to convert
 * @return The resulting string */
public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements) {
    return stackTraceCausedByElementsOnlyToStr(stackTraceElements, "\n");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @return The resulting string */
public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements, String lineSeparator) {
    return stackTraceCausedByElementsOnlyToStr(stackTraceElements, lineSeparator, "");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting string */
public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements, String lineSeparator, String padding) {
    String str = "";
    if(stackTraceElements != null) {
        for(StackTraceElement stackTrace : stackTraceElements) {
            str += (!stackTrace.toString().startsWith("Caused By") ? "" : padding + stackTrace.toString() + lineSeparator);
        }
    }
    return str;
}

/** @param e The {@link Throwable} to convert
 * @return The resulting String */
public static final String throwableToStrNoStackTraces(Throwable e) {
    return throwableToStrNoStackTraces(e, "\n");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @return The resulting String */
public static final String throwableToStrNoStackTraces(Throwable e, String lineSeparator) {
    return throwableToStrNoStackTraces(e, lineSeparator, "");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting String */
public static final String throwableToStrNoStackTraces(Throwable e, String lineSeparator, String padding) {
    if(e == null) {
        return "null";
    }
    String str = e.getClass().getName() + ": ";
    if((e.getMessage() != null) && !e.getMessage().isEmpty()) {
        str += e.getMessage() + lineSeparator;
    } else {
        str += lineSeparator;
    }
    str += padding + stackTraceCausedByElementsOnlyToStr(e.getStackTrace(), lineSeparator, padding);
    for(Throwable suppressed : e.getSuppressed()) {
        str += padding + throwableToStrNoStackTraces(suppressed, lineSeparator, padding + "\t");
    }
    Throwable cause = e.getCause();
    while(cause != null) {
        str += padding + "Caused by:" + lineSeparator + throwableToStrNoStackTraces(e.getCause(), lineSeparator, padding);
        cause = cause.getCause();
    }
    return str;
}

/** @param e The {@link Throwable} to convert
 * @return The resulting String */
public static final String throwableToStr(Throwable e) {
    return throwableToStr(e, "\n");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @return The resulting String */
public static final String throwableToStr(Throwable e, String lineSeparator) {
    return throwableToStr(e, lineSeparator, "");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting String */
public static final String throwableToStr(Throwable e, String lineSeparator, String padding) {
    if(e == null) {
        return "null";
    }
    String str = padding + e.getClass().getName() + ": ";
    if((e.getMessage() != null) && !e.getMessage().isEmpty()) {
        str += e.getMessage() + lineSeparator;
    } else {
        str += lineSeparator;
    }
    str += padding + stackTraceElementsToStr(e.getStackTrace(), lineSeparator, padding);
    for(Throwable suppressed : e.getSuppressed()) {
        str += padding + "Suppressed: " + throwableToStr(suppressed, lineSeparator, padding + "\t");
    }
    Throwable cause = e.getCause();
    while(cause != null) {
        str += padding + "Caused by:" + lineSeparator + throwableToStr(e.getCause(), lineSeparator, padding);
        cause = cause.getCause();
    }
    return str;
}

Пример:

try(InputStream in = new FileInputStream(file)) {
    ...
} catch(IOException e) {
    String exceptionToString = throwableToStr(e);
    someLoggingUtility.println(exceptionToString);
    ...
}

Печать:

java.io.FileNotFoundException: C:\test.txt (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(Unknown Source)
    at java.io.FileInputStream.<init>(Unknown Source)
    at com.gmail.br45entei.Example.main(Example.java:32)
0

Несколько вариантов

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

  2. Использование Google Guava lib String stackTrace = Throwables.getStackTraceAsString( myException ) ;

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

0

Используйте exp.printStackTrace() для отображения стека вашего исключения.

try {
   int zero = 1 - 1;
   int a = 1/zero;
} catch (Exception e) {
    e.printStackTrace();
}
0

Предупреждение: это может быть немного не по теме, ну да ладно...;)

Я не знаю, какова была первоначальная причина постеров для того, чтобы в первую очередь хотеть трассировки стека как строки. Когда трассировка стека должна заканчиваться в SLF4J/Logback LOG, но здесь не было и не должно быть исключения, что я делаю:

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
}

Мне это нравится, потому что для этого не требуется внешняя библиотека (кроме вашей серверной части, которая, конечно же, будет работать в большинстве случаев).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню