Использование Строки (Строка) конструктор в Java [дубликат]

В то время как постоянный слой имеет смысл, вы должны создать его по-другому. То, что вы делаете, это упаковываете некоторую сложность в методы, которые все еще делают то же самое, такие как ChangeParam() или GetDataReader().

Как правило, у вас есть репозитории, которые знают о базовых технических особенностях и устраняют такие сложности, как GetAllCustomers() (с акцентом на доменное имя customer ).

Когда вы скажете 4 или 5 таких хранилищ, вы начнете рефакторинг, абстрагируя сложность в родительский класс. Таким образом, вы упаковываете сложность, такую ​​как в GetDataReader() и , продвигаете ее из репозиториев в абстрактный репозиторий , который находится поверх него.

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

Если бы это было так просто, API ADO.NET уже удалил бы его.

Еще одна вещь, которую вы должны сделать, это взглянуть на этот простой, но постоянно повторяющийся фрагмент кода. Он перегоняет некоторые основные понятия о IDisposable и using(){}. Вы всегда встретите его в правильном коде:

string sql = "SELECT * FROM t";

using (SqlConnection con = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(sql, con))
{
    SqlDataReader reader;

    con.Open();
    reader = cmd.ExecuteReader();

    while (reader.Read())
    {
        // TODO: consume data
    }
    reader.Close();
}

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

11
задан Bhargav Rao 19 August 2019 в 01:15
поделиться

6 ответов

Это - хорошая статья: Представьте в виде строки конструктора, которого рассматривают бесполезным, оказывается полезным, в конце концов!

Оказывается, что этот конструктор может на самом деле быть полезным при по крайней мере одном обстоятельстве. Если Вы когда-либо посмотрели на Строковый исходный код, Вы будете видеть, что он только имеет поля для значения массива символов и количества символов, но также и для смещения к началу Строки. Это - то, так, чтобы Строки могли совместно использовать значение массива символов с другими Строками, обычно следует из вызова одной из подстроки () методы. Java заметно отчитывался за это в jwz' напыщенная речь Java с лет назад:

Единственная причина этих издержек состоит в том так, чтобы String.substring () мог возвратить строки, которые совместно используют тот же массив значения. Выполнение этого за счет добавления 8 байтов к каждому Строковому объекту не является чистыми сбережениями...

Сбережения байта в стороне, если у Вас есть некоторый код как это:

// imagine a multi-megabyte string here  
String s = "0123456789012345678901234567890123456789";  
String s2 = s.substring(0, 1);  
s = null;

У Вас теперь будет Строка s2, который, хотя это, кажется, одна символьная строка, содержит ссылку на гигантский массив символов, созданный в Строке s. Это означает, что массив не будет собран "мусор", даже при том, что мы явно обнулили Строку s!

Фиксация для этого должна использовать нашего ранее упомянутого "бесполезного" конструктора String как это:

String s2 = new String(s.substring(0, 1));  

Это не известно, что этот конструктор на самом деле копирует это старое содержание в новый массив, если старый массив больше, чем количество символов в строке. Это означает, что старое Строковое содержание будет собрано "мусор", как предназначено. Счастливая счастливая радость радости.

Наконец, Kat Marsen делает эти точки,

В первую очередь, строковые константы никогда не собираются "мусор". Второй из всех, строковые константы являются intern'd, что означает, что они совместно используются через весь VM. Это сохраняет память. Но это не всегда, чего Вы требуете.

Конструктор копии на Строке позволяет Вам создавать частный Строковый экземпляр из Строкового литерала. Это может быть очень ценно для построения значимых взаимоисключающих объектов (в целях синхронизации).

41
ответ дан 3 December 2019 в 00:49
поделиться

Только, чтобы подробно остановиться на ответе Douglas*, я могу дать твердый пример того, где я использовал его. Рассмотрите чтение файла словаря, с тысячами строк, каждым из них просто отдельное слово. Самый простой способ считать это состоит в том, чтобы использовать BufferedReader.readLine().

К сожалению, readLine() выделяет буфер 80 символов по умолчанию как ожидаемая длина строки. Это означает, что обычно может избежать бессмысленного копирования - и немного потраченной впустую памяти не обычно слишком плохо. Однако при загрузке словаря коротких слов в на время приложения Вы заканчиваете с большой постоянно потраченной впустую памятью. Мое "небольшое приложение", высосанное намного больше памяти, чем он, должно было сделать.

Решение состояло в том, чтобы изменить это:

String word = reader.readLine();

в это:

String word = new String(reader.readLine());

... с комментарием, конечно!

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

8
ответ дан 3 December 2019 в 00:49
поделиться

Если я помню правильно, что единственный 'полезный' случай - то, где исходная строка является частью намного большего вспомогательного массива. (например, созданный как подстрока). Если Вы только хотите иметь в наличии маленькую подстроку и собрать "мусор" большой буфер, могло бы иметь смысл создавать новую Строку.

11
ответ дан 3 December 2019 в 00:49
поделиться

Конструктор в основном избыточен и не рекомендуемый для общих целей. Строковый конструктор с Аргументом строки редко используется кроме создать независимую копию существующей строковой переменной. В основном используйте его для "разъяснения" кода. Ничто меньше.

0
ответ дан 3 December 2019 в 00:49
поделиться

от javadoc

/**
 * Initializes a newly created {@code String} object so that it represents
 * the same sequence of characters as the argument; in other words, the
 * newly created string is a copy of the argument string. Unless an
 * explicit copy of {@code original} is needed, use of this constructor is
 * unnecessary since Strings are immutable.
 *
 * @param  original
 *         A {@code String}
 */
public String(String original){.....}
0
ответ дан 3 December 2019 в 00:49
поделиться

Вы используете его при необходимости в копии исходной строки, если Вы не хотите давать дескриптор своей исходной строке. Но так как строки неизменны, я не вижу варианта использования fot это ;)

-2
ответ дан 3 December 2019 в 00:49
поделиться
Другие вопросы по тегам:

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