Каков лучший способ проанализировать строки? [закрытый]

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

6
задан Torsten Marek 26 September 2008 в 16:57
поделиться

10 ответов

Эти три решения, которые Вы заявили каждому, удовлетворяют совсем другие потребности.

Парсинг руководства (простой текстовый поиск) является самым гибким и самым адаптируемым, однако, это очень быстро становится реальной болью в заднице, поскольку требуемый парсинг более сложен.

Regex являются вторым планом и вероятно Вашим лучшим выбором здесь. Они мощны, все же гибки, поскольку можно самостоятельно добавить больше логики из кода, которые называют другой regex. Основной недостаток был бы скоростью здесь.

Lex/Yacc действительно только адаптирован к очень сложным, предсказуемым синтаксисам и испытывает недостаток в большой гибкости компиляции сообщения. Вы не можете легко изменить синтаксический анализатор в середине парсинга, хорошо на самом деле Вы можете, но это быть просто слишком тяжелыми, и Вы лучше использовали бы regex вместо этого.

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

Как альтернатива, как Vaibhav poionted, если у Вас есть несколько различных ситуаций, которые могут возникнуть и что Вы cna легко обнаруживаете, какой прибывает, Вы могли сделать сменную систему, которая выбирает правильный алгоритм, и те алгоритмы могли все очень отличаться, одно использование Lex/Yacc в заостренных случаях и другом использовании IndexOf и regex для более простых случаев.

4
ответ дан 9 December 2019 в 22:42
поделиться

Regex.

Regex может решить почти все за исключением мира во всем мире. Хорошо, возможно, мир во всем мире также.

5
ответ дан 9 December 2019 в 22:42
поделиться

У Вас, вероятно, должна быть сменная система, независимо от которого типа строки, анализирующей Вас, используют. Так, это системные вызовы на правильный 'плагин' в зависимости от типа электронной почты для парсинга его.

1
ответ дан 9 December 2019 в 22:42
поделиться

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

В рамках Вашей конфигурации определите тип синтаксического анализатора, Вы хотите использовать, установить его параметры конфигурации и конфигурацию для идентификаторов, которые определяют, будет ли синтаксический анализатор действовать или нет. Назовите синтаксические анализаторы полностью определенным именем блока так, чтобы типы можно было инстанцировать во времени выполнения, даже если нет статических ссылок на их блоки.

Идентификаторы могут реализовать интерфейс также, таким образом, можно создать различные типы та проверка на разные вещи. Например, Вы могли бы создать regex идентификатор, который анализирует электронную почту для определенного шаблона. Удостоверьтесь, что сделали столько же информации доступным идентификатору, так, чтобы это могло принять решения о вещах как от адресов, а также содержания электронной почты.

Когда Ваши известные синтаксические анализаторы не могут обработать задание, создать новый DLL с типами, которые реализуют синтаксический анализатор и интерфейсы идентификатора, которые могут обработать задание и отбросить их в Вашем каталоге bin.

1
ответ дан 9 December 2019 в 22:42
поделиться

Это зависит от того, что Вы анализируете. Для чего-либо вне того, что может обработать Regex, я использовал ANTLR. Прежде чем Вы вскочите в синтаксический анализ методом рекурсивного спуска впервые, я исследовал бы, как они работают, прежде, чем попытаться использовать платформу как этот. Если Вы подписываетесь на MSDN Magazine, проверьте выпуск февраля 2008, где у них есть статья о записи той с нуля.

После того как Вы получаете понимание, узнавая, что ANTLR будет легче тонной. Там существуют другие платформы, но ANTLR, кажется, имеет большую часть общественной поддержки и общедоступной документации. Автор также опубликовал Категорическую Ссылку ANTLR: Создание Проблемно-ориентированных Языков.

1
ответ дан 9 December 2019 в 22:42
поделиться

Regex, вероятно, был бы Вами ставка bes, которую попробовали и доказанный. Плюс регулярное выражение может быть скомпилирован.

0
ответ дан 9 December 2019 в 22:42
поделиться

С такой же небольшой информацией Вы, если, я выбрал бы Regex.

Но то, какую информацию Вы хотите проанализировать и что Вы хотели бы сделать, изменит решение на Lex/Yacc, возможно..

Но похоже, что Вы уже составили свой ум с Поиском строки :)

-1
ответ дан 9 December 2019 в 22:42
поделиться

@Coincoin покрыл основания; я просто хочу добавить, что с regex особенно легко закончиться с твердым к чтению, твердо обслуживаемым кодом. Regex является мощным и очень компактным языком, таким образом, это - то, как он часто идет.

Используя пробел и комментарии в regex может пойти длинным путем, чтобы помочь поддержать regexes. Eric Gunnerson включил меня к этой идее. Вот пример.

0
ответ дан 9 December 2019 в 22:42
поделиться

Вашим лучшим выбором является RegEx, потому что он обеспечивает намного большую степень гибкости, чем любая из других опций.

В то время как Вы могли использовать IndexOf для обработки somethings можно быстро найти себя написанием кода, которое похоже:

if(s.IndexOf("search1")>-1 || s.IndexOf("search2")>-1 ||...

Это может быть обработано в одном операторе RegEx. Плюс, существует много места как RegExLib.com, где можно найти людей, которые совместно использовали регулярные выражения для решения проблем.

0
ответ дан 9 December 2019 в 22:42
поделиться

Используйте PCRE. Все остальные ответы - только 2-е место.

0
ответ дан 9 December 2019 в 22:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: