StringBuilder добавляет null как "null"

Как так?

    StringBuilder sb = new StringBuilder();

    sb.append("Hello");
    sb.append((String)null);
    sb.append(" World!");
    Log.d("Test", sb.toString());

Производит

06-25 18: 24: 24.354: D/Test (20740): World Hellonull!

Я ожидаю, что добавление null String будет вообще не добавляться !!
BTW, приведение к String необходимо, потому что StringBuilder.append() имеет много перегруженных версий.

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

public String getString() { ... }
...
sb.append(getString());
...

getString() sometimes returns null; now I have to test it if I want to use a StringBuilder!!!!

Кроме того, давайте проясним мой вопрос здесь: как я могу получить StringBuilder.append() , чтобы элегантным образом принять пустую строку и не преобразовать ее в литеральную строку «null».
Изящным я имею в виду, что я не хочу получать строку, проверяю, является ли это null и только потом добавляет ее. Я ищу элегантный oneliner.

5
добавлено автор Stephen C, источник

10 ответы

How come?

Its clearly written in docs

Символы аргумента String добавляются, чтобы увеличить длину этой последовательности по длине аргумента. Если str равно NULL, то добавляются четыре символа «null».

Поэтому, пожалуйста, поставьте нулевую проверку перед добавлением.

5
добавлено
Хорошо, это написано в документации. Но, разве это просто я очень противен? Я узнал, что пустая строка - это строка, которая не существует. И, не открывая дискуссии, я просто не понимаю, почему они это сделали. Прямо сейчас я стучу головой по столу.
добавлено автор ilomambo, источник
@LastFreeNickname Не действительно, когда строка null Я не хочу/не хочу ничего видеть. Если я использую отладчик, я хочу проверить эту переменную и увидеть ее значение как null . Похоже, что не так давно в алгебрном курсе профессор сказал, что есть специальный символ, обозначающий пустой набор, набор без элементов вообще, который является аналогом пустой строки. Отображение чего-то для нулевой строки ломает согласованность с тем же самым определением null . Но это плачет о пролитом молоке, когда-нибудь я надеюсь узнать причину.
добавлено автор ilomambo, источник
Я думаю, вы путаете пустую строку и пустую строку. Как вы говорите, (String) null - это String, которая не существует, которая представлена ​​«null» в домене String. С другой стороны, пустая строка "" неудивительно имеет представление "". Когда вы отлаживаете или печатаете какую-либо переменную String, вы хотите увидеть, что она указывает на значение NULL, поэтому имеет смысл.
добавлено автор LastFreeNickname, источник

Так оно и есть. null добавляется как "null" . Аналогично, когда вы печатаете null с помощью System.out.println (null) , вы печатаете "null" .

Способ избежать этого - это метод, возвращающий строку getString() для null :

public String getString() {
    ...
    if (result == null) {
        return "";
    }
}
4
добавлено

EDIT
My previous answer was not reflecting the appropriate reason for such behaviour of StringBuilder as asked by OP. Thanks to @Stephen C for pointing out that

Я ожидаю, что добавление нулевой строки не будет вообще добавляться !!

Но это добавление. Причина такого поведения StringBuilder скрыта в детали реализации метода append (Object obj) , который приводит нас к AbstractStringBuilder # append (String str) , который определяется следующим образом:

public AbstractStringBuilder append(String str) {
    if (str == null) str = "null"; -->(1)
    //.......
    return this;
}

Он ясно указывает, что если входной код String равен нулю, тогда он изменяется на строковый литерал «null», а затем он обрабатывается дальше.

Как я могу заставить StringBuilder.append() принять элегантным способом пустую строку и не преобразовывать ее в строку «null».

Вам нужно проверить явно указанный String для null , а затем продолжить. Например:

String s = getString();
StringBuffer buf = new StringBuffer();
//Suppose you want "Hello "" world"
buf.append("Hello ");
buf.append(s==null?" world" : s+" world");
2
добавлено
Строго говоря, JLS для этого не является окончательным. JLS фактически задает семантику оператора «+». Вы можете утверждать, что удобно совпадение, что StringBuilder.append (null) реализует требуемое поведение. (Я уверен, что это не совпадение, но вы понимаете мое мнение ...)
добавлено автор Stephen C, источник
@StephenC: Да, вы правы. Моя ошибка ..
добавлено автор Vishal K, источник

Он ведет себя так, потому что null не является пустым String , как вы думаете об этом. Пустой String будет new String (""); . В основном метод append() добавляет "null" , если он получает значение null в качестве параметра.

2
добавлено
Я не сказал «пустая строка», я сказал «строка, которая не существует»
добавлено автор ilomambo, источник

Это будет работать для вас

public static String getString(StringBuilder sb, String str) {
    return sb.append(str == null ? "" : str).toString();
}
1
добавлено

AbstractStringBuilder class appends an object through String.valueOf(obj) method which in turn converts NULL into string literal "null". Therefor there is no inbuilt method to help you here. You have to either use ternary operator within append method or write a utility method to handle it, as others suggested.

1
добавлено

Как насчет написания метода полезности, например

public static void appendString(StringBuilder sb, String st) {
    sb.append(st == null ? "" : st);
}

или это тернарный оператор очень удобен.

0
добавлено

Вы также можете написать декоратор для StringBuilder, который может проверять все, что вы хотите:

class NotNullStringBuilderDecorator {

    private StringBuilder builder;

    public NotNullStringBuilderDecorator() {
        this.builder = new StringBuilder();
    }

    public NotNullStringBuilderDecorator append(CharSequence charSequence) {
        if (charSequence != null) {
            builder.append(charSequence);
        }

        return this;
    }

    public NotNullStringBuilderDecorator append(char c) {
        builder.append(c);

        return this;
    }

    //Other methods if you want

    @Override
    public String toString() {
        return builder.toString();
    }
}

Пример использования:

NotNullStringBuilderDecorator sb = new NotNullStringBuilderDecorator();
sb.append("Hello");
sb.append((String) null);
sb.append(" World!");

System.out.println(sb.toString());

С помощью этого решения вы не должны изменять классы POJO.

0
добавлено
String nullString = null;
StringBuilder sb = new StringBuilder();
sb.append("Hello");
if (nullString != null) sb.append(nullString);
sb.append(" World!");
Log.d("Test", sb.toString());

Там! Я сделал это в одной строке :)

0
добавлено
:-) Без вопросов это очень элегантно :-)
добавлено автор ilomambo, источник

Одна линия?

sb.append((getString()!=null)?getString():"");

сделанный. Но бессмысленно, так как нужно дважды вызвать getString()

Как было предложено построить проверку в getString() метод

0
добавлено
Mobile Dev Jobs — вакансии и аналитика
Mobile Dev Jobs — вакансии и аналитика
6 187 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin и т.д. ВАЖНО: Правила публикации и правила канала: Ссылка – https://telegra.ph/Pravila-oformleniya-vakansij-i-rezyume-11-09-2

Android Developers
Android Developers
4 476 участник(ов)

Общаемся на темы, посвященным Android-разработке, SDK, Kotlin, Realm и т.д.

pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Java & Co
Java & Co
2 370 участник(ов)

Можно обсуждать с матом и без всё, что касается жабы, вплоть до холиваров. НЕ ИМЕЕТ ОТНОШЕНИЯ К САЙТУ JAVARUSH.RU ПРАВИЛА - https://t.me/javarush/75723 Вакансии сюда - https://telegram.me/joinchat/B7IzvUCnfo6d8t3yIxKguQ По вопросам - @thedude

Android Architecture
Android Architecture
2 186 участник(ов)

Русскоязычный чат по архитектуре в андроид приложениях. Подробнее: http://telegra.ph/Android-Architecture-12-24

learn.java
learn.java
1 888 участник(ов)

Чат для начинающих и не только Статистика: https://combot.org/chat/-1001083535868 Основной чат - @jvmchat

rus-speaking/android
rus-speaking/android
1 705 участник(ов)

Основной чат по Android разработке (вопрос-ответ). ПРАВИЛА: bit.ly/andr-rules. NEWS: bit.ly/AnrdResId ЧАТЫ: Основной: bit.ly/andr-main IDE, сборка, Git, сервисы: bit.ly/andr-tools Оффтоп: bit.ly/andr-offtop Конференции, события: bit.ly/andr-events Вакансии, найм: bit.ly/andr-job Архитектура: bit.ly/andr-patterns Rx: bit.ly/andr-rx Тестирование: bit.ly/andr-test Kotlin: bit.ly/andr-kotlin Хаmarin: bit.ly/andr-xamarin За мат, спам, агрессию, предложения о работе, оффтоп в этом канале - бан на сутки и более ☢☢☢

Android Dev Подкаст
Android Dev Подкаст
1 325 участник(ов)

Комната для обсуждения Android Dev подкаста apptractor.ru/AndroidDev/ Общее обсуждение Android: https://t.me/android_ru Остальные чаты про Android: http://t.me/devChats Наши новости https://t.me/androiddevpodcast_news

Android Guards
Android Guards
602 участник(ов)

Обсуждение любых вопросов касающихся безопасности Android. - Защита системы и приложений - Уязвимости и эксплойты - Вредоносное ПО - Копание в кишках системы и приложений (RE)

Android JOB
Android JOB
466 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению Android (full-time, part-time, remote и разовые подработки)

AndroidDev :: Разработка. It's Android time now!
AndroidDev :: Разработка. It's Android time now!
458 участник(ов)

It's Android time now! Чат разработчиков Android. Вакансии, резюме и информацию о митапах размещать можно. Публикацию скрытой и явной рекламы ваших каналов и сайтов после получения разрешения от @olegushakov

Aandroid Talks!
Aandroid Talks!
212 участник(ов)

Чат об общих вопросах по ОС Android. Чат для разработки под андроид - pro.android: https://t.me/joinchat/AAAAAEKIFKnmRT9cMebb9w

Java Underground
Java Underground
169 участник(ов)

https://vk.com/javatutorial

Javanese Questions
Javanese Questions
109 участник(ов)

Чат предназначен для обмена знаниями строго в формате в вопрос-ответ. Тема — Java, Kotlin и Android. Вопрос должен быть предварительно прогуглен, понятно и грамотно сформулирован, помечен хэштегами. Ответ — тем более. Куски кода размером в несколько строк можно писать прямо здесь, для больших кусков кода стоит использовать http://gist.github.com/, http://pastebin.com/, https://codeshare.io/ или любой аналогичный сервис. В некоторых случаях можно прикреплять скриншоты. Стикеры и гифки запрещены. Дополнять и уточнять вопросы и ответы — редактированием исходного сообщения. Обсуждения должны приводить к редактированию вопроса/ответа и удаляться. По хештегам можно искать существующие вопросы и овтеты: #вопрос #ответ #git #generics #java #server #awt #javafx #swing #kotlin #anko #tornadofx #ktor #android #recyclerView #performance #arch #network #permissions #storage #async

Android Rus
Android Rus
68 участник(ов)