Хорошим местом для начала является JavaDocs . Они охватывают это:
Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
- Вызов метода экземпляра нулевого объекта.
- Доступ или изменение поля нулевого объекта.
- Выполнение длины null, как если бы это был массив.
- Доступ или изменение слотов с нулевым значением, как если бы это был массив.
- Бросать нуль, как если бы это было значение Throwable.
Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.
blockquote>Также, если вы попытаетесь использовать нулевую ссылку с
synchronized
, который также выдаст это исключение, за JLS :SynchronizedStatement: synchronized ( Expression ) Block
blockquote>
- В противном случае, если значение выражения равно null,
NullPointerException
.Как это исправить?
Итак, у вас есть
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 = "";
Либо метод
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 ).
Обычно выбирайте CHAR, если все строки будут иметь близко к та же длина . Выберите VARCHAR, когда длина будет варьироваться значительно. CHAR может также быть немного быстрее, потому что все строки имеют ту же длину.
Это варьируется реализацией DB, но обычно VARCHAR использует один или еще два байта устройства хранения данных (для длины или завершения) в дополнение к фактическим данным. Таким образом (принимающий Вы используете набор однобайтового символа), хранение слова "FooBar"
, Нижняя строка , CHAR может быть быстрее , и больше располагает с интервалами эффективный для данных относительно той же длины (в двух различиях в длине символов).
Примечание : Microsoft SQL имеет 2 байта издержек для VARCHAR. Это может варьироваться от DB до DB, но обычно существует по крайней мере 1 байт издержек, должен был указать на длину или EOL на VARCHAR.
, Как был указан Gaven в комментариях при использовании многобайтового набора символов переменной длины как UTF8 тогда CHAR хранит максимальное количество байтов, необходимых для хранения количества символов. Таким образом, если UTF8 будут нужны самое большее 3 байта для хранения символа, то CHAR (6) будет зафиксирован на уровне 18 байтов, даже если только хранение latin1 символы. Таким образом, в этом случае VARCHAR становится намного лучшим выбором.
В некоторых базах данных SQL VARCHAR будет увеличен к его максимальному размеру для оптимизации смещений, Это должно ускорить полные сканирования таблицы и индексы.
из-за этого, у Вас нет сбережений пространства при помощи VARCHAR (200) по сравнению с CHAR (200)
когда использование varchar оценивает потребности SQL Server дополнительные 2 байта за строку для хранения некоторой информации о том столбце, тогда как при использовании символа этому не нужно это поэтому если Вы
Я думаю в Вашем случае нет, вероятно, никакой причины не выбрать Varchar. Это дает Вам гибкость и как был упомянут многими респондентами, производительность - такой теперь, когда кроме очень определенных обстоятельств нас meer смертные (в противоположность DBA Google) не заметят различия.
интересной вещью, которую стоит отметить когда дело доходит до Типов БД, является sqlite (популярная мини-база данных с довольно впечатляющей производительностью) помещает все в базу данных как строка и типы на лету.
я всегда использую VarChar и обычно делаю его намного больше, чем я мог бы потребность strickly. Например, 50 для Firstname, поскольку Вы говорите, почему не только быть в безопасности.
Это - классическое пространство по сравнению с компромиссом производительности.
В SQL MS 2005, Varchar (или NVarchar для lanuagues требование двух байтов за символ т.е. китайский язык) являются переменной длиной. Если Вы добавите к строке после того, как она была записана в жесткий диск, то она определит местоположение данных в non-contigious месте к исходной строке и приведет к фрагментации Ваших файлов данных. Это будет влиять на производительность.
Так, если пространство не является проблемой тогда, Символ лучше для производительности, но если Вы хотите подавить размер базы данных тогда varchars, лучше.
Существует некоторая маленькая обработка наверху в вычислении фактического необходимого размера для значения столбца и выделения места для Varchar, поэтому если Вы определенно уверены, какой длины значение всегда будет, лучше использовать Символ и избежать хита.
Многие люди указали, что, если Вы знаете, точная длина значения с помощью CHAR обладает некоторыми преимуществами. Но при хранении штатов США, поскольку CHAR (2) является большим сегодня, когда Вы получаете сообщение от продаж, что 'Мы только что сделали нашу первую продажу Австралии', Вы находитесь в мире боли. Я всегда отправляю к переоценке, сколько времени я думаю, что поля должны будут быть вместо того, чтобы высказать 'точное' предположение для покрытия для будущих событий. VARCHAR даст мне больше гибкости в этой области.
CHAR поднимает меньше пространства памяти, чем VARCHAR, если все Ваши значения данных в том поле являются той же длиной. Теперь, возможно, в 2009 база данных на 800 ГБ является тем же, во всех отношениях, как 810 ГБ, если Вы преобразовали VARCHARs в СИМВОЛЫ, но для коротких строк (1 или 2 символа), CHAR является все еще промышленностью "лучшая практика", которую я сказал бы.
Теперь при рассмотрении большого разнообразия типов данных большинство баз данных обеспечивает даже для одних только целых чисел (бит, крошечный, международный, bigint), СУЩЕСТВУЮТ причины выбрать один по другому. Просто выбор bigint каждый раз на самом деле немного незнаком с целями и использованием поля. Если поле просто представляет возраст людей в годах, bigint является излишеством. Теперь это не обязательно "неправильно", но это не эффективно.
, Но интересный аргумент, и как базы данных улучшается со временем, это мог быть обсужденный CHAR по сравнению с VARCHAR, действительно становится менее релевантным.
Я выбрал бы varchar, если столбец не хранит фиксированное значение как Американский Государственный код - который является всегда 2 символами долго, и список допустимого кода штатов США часто не изменяется:).
В любом случае, даже как хранение хешированного пароля (который является фиксированной длиной), я выбрал бы varchar.
, Почему - символьный столбец типа всегда выполняется с пробелами, который делает для столбца my_column определенный как символ (5) со значением 'ABC' внутри comparation:
my_column = 'ABC' -- my_column stores 'ABC ' value which is different then 'ABC'
ложь.
Этот функция могла привести ко многим раздражающим ошибкам во время разработки и делает тестирование тяжелее.
Существует различие между ранней оптимизацией производительности и использованием типа лучшей практики правила. Если Вы составляете новые таблицы, где у Вас всегда будет поле фиксированной длины, имеет смысл использовать CHAR, необходимо использовать его в этом случае. Это не ранняя оптимизация, а скорее реализация эмпирического правила (или лучшая практика).
т.е. - если у Вас есть 2 поля состояния буквы, используйте CHAR (2). Если у Вас есть поле с именами реального положения, используйте VARCHAR.
Существуют выигрыши в производительности, но вот тот, который не был упомянут: миграция строки. С символом Вы резервируете все пространство заранее. Поэтому позвольте нам, говорит, что у Вас есть символ (1000), и Вы храните 10 символов, Вы израсходуете все 1 000 символов пространства. В varchar2 (1000), Вы будете только использовать 10 символов. Проблема возникает при изменении данных. Скажем, Вы обновляете столбец, чтобы теперь содержать 900 символов. Возможно, что пространство для расширения varchar не доступно в текущем блоке. В этом случае механизм DB должен переместить строку в другой блок и сделать указатель в исходном блоке к новой строке в новом блоке. Для чтения этих данных механизм DB должен будет теперь считать 2 блока.
Никто не может двусмысленно сказать, что varchar или символ лучше. Существует пространство для компромисса времени и рассмотрение того, будут ли данные обновлены, особенно если существует хороший шанс, что это вырастет.
Символ немного быстрее, поэтому если у Вас будет столбец, который Вы ЗНАЕТЕ, то будет определенная длина, использовать символ. Например, храня (M) пиво / (F) emale / (U) nknown для пола или 2 символов для штата США.
В дополнение к выигрышам в производительности, CHAR
может использоваться, чтобы указать, что все значения должны быть той же длиной, например, столбец для Американских Государственных сокращений.
Если бы Вы работаете со мной, и Вы работаете с Oracle, я, вероятно, заставил бы Вас использовать varchar
почти при каждом обстоятельстве. Предположение, что char
использование меньше вычислительной мощности, чем varchar
может быть верным... на данный момент..., но механизмы базы данных поправляются со временем и этот вид общего правила, имеет создание из будущего "мифа".
Другая вещь: Я никогда не видел проблемы производительности, потому что кто-то решил пойти с varchar
. Вы будете намного лучше использовать свое время, пишущий хороший код (меньше вызовов к базе данных) и эффективный SQL (как делают индексную работу, как оптимизатор принимает решения, почему exists
быстрее, чем in
обычно...).
Последняя мысль: Я видел все виды проблем с использованием CHAR
, люди, ищущие, '' когда они должны искать '', или люди, ищущие 'НЕЧТО', когда они должны искать 'НЕЧТО (набор пробелов здесь)', или люди, не обрезающие конечные пробелы или ошибки с Powerbuilder, составляющим в целом 2 000 пробелов к значению, это возвращается из процедуры Oracle.
Я поддерживаю комментарий Jim McKeeth.
кроме того, индексируя и полные сканирования таблицы быстрее, если Ваша таблица имеет только столбцы CHAR. В основном оптимизатор будет в состоянии предсказать, насколько большой каждая запись - то, если это только имеет столбцы CHAR, в то время как это должно проверить значение размера каждого столбца VARCHAR.
, Кроме того, если Вы обновляете столбец VARCHAR к размеру, больше, чем его предыдущее содержание, можно вынудить базу данных восстановить свои индексы (потому что Вы вынудили базу данных физически переместить запись в диск). В то время как со столбцами CHAR этого никогда не будет происходить.
, Но Вы, вероятно, не будете заботиться о хите производительности, если Ваша таблица не будет огромна.
Помнят мудрые слова Djikstra. Ранняя оптимизация производительности является корнем всего зла.