Другое событие NullPointerException
возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.
String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals
для гарантированного непустого объекта.
Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null
.
Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.
String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
MSDN:
хеш-функция А должна иметь следующие свойства:
- , Если два объекта выдерживают сравнение как равные,
GetHashCode
, метод для каждого объекта должен возвратить то же значение. Однако, если два объекта не выдерживают сравнение как равные, этиGetHashCode
, методы для этих двух объектов не должны возвращать различные значения.GetHashCode
метод для объекта должен последовательно возвращать тот же хэш-код, пока нет никакой модификации к объектному состоянию, которое определяет возвращаемое значение объектаEquals
метод. Обратите внимание, что это верно только для текущего выполнения приложения, и что различный хэш-код может быть возвращен, если приложение запущено снова.- Для лучшей производительности, хеш-функция должна генерировать случайное распределение для всего входа.
Взятие это во внимание исправляет путь:
return str1.GetHashCode() ^ str2.GetHashCode()
^
может быть заменен с другой коммутативной операцией
public override int GetHashCode()
{
unchecked
{
return (str1 ?? String.Empty).GetHashCode() +
(str2 ?? String.Empty).GetHashCode();
}
}
Используя '+' оператор мог бы быть лучше, чем использование '^ ', потому что, хотя Вы явно хотите ('AA', 'BB') и ('BB', 'AA') явно быть тем же, Вы не можете хотеть ('AA', 'AA') и ('BB', 'BB') быть тем же (или все равные пары в этом отношении).
'максимально быстро' правило не полностью придерживается к в этом решении, потому что в случае пустых указателей это выполняет 'GetHashCode ()' на пустой строке, а не сразу возвратите известную константу, но даже явно не имея размеры я готов рисковать предположением, что различие не было бы достаточно большим для волнения о том, если Вы не ожидаете много пустых указателей.
Как правило, простым способом генерировать хэш-код для класса являются к XOR все поля данных, которые могут участвовать в генерации хэш-кода (старающийся для проверки на пустой указатель, как указано другими). Это также встречается (искусственный?) требование, чтобы хэш-коды для UserInfo ("AA", "BB") и UserInfo ("BB", "AA") были тем же.
, Если можно сделать предположения об использовании класса, можно, возможно, улучшить хеш-функцию. Например, если str1 и str2 свойственно быть тем же, XOR не может быть хорошим выбором. Но если str1 и str2 представляют, скажем, имя и фамилию, XOR является, вероятно, хорошим выбором.
, Хотя это ясно не предназначено, чтобы быть реальным примером, может стоить указать что: - это - вероятно, плохой пример использования структуры: структура должна обычно иметь семантику значения, которая, кажется, не имеет место здесь. - Используя свойства с методами set для генерации хэш-кода также напрашивается на неприятности.
public override int GetHashCode()
{
unchecked
{
return(str1 != null ? str1.GetHashCode() : 0) ^ (str2 != null ? str2.GetHashCode() : 0);
}
}
А-ч да, как Gary Shutler указал:
return str1.GetHashCode() + str2.GetHashCode();
Может переполниться. Вы могли попытаться снять к долго в качестве Артема, предложенного, или Вы могли окружить оператор в ключевом слове непроверенном:
return unchecked(str1.GetHashCode() + str2.GetHashCode());
Испытайте этого:
(((long)str1.GetHashCode()) + ((long)str2.GetHashCode())).GetHashCode()
Много возможностей. Например,
return str1.GetHashCode() ^ str1.GetHashCode()
Возможно, что-то как str1. GetHashCode () + str2. GetHashCode ()? или (str1. GetHashCode () + str2. GetHashCode ()) / 2? Таким образом, это было бы то же независимо от того, подкачиваются ли str1 и str2....
Отсортируйте их, затем свяжите их:
return ((str1.CompareTo(str2) < 1) ? str1 + str2 : str2 + str1) .GetHashCode();
Результат GetHashCode, как предполагается:
Мысль о тех, я пошел бы с чем-то вроде этого:
if (str1 == null)
if (str2 == null)
return 0;
else
return str2.GetHashCode();
else
if (str2 == null)
return str1.GetHashCode();
else
return ((ulong)str1.GetHashCode() | ((ulong)str2.GetHashCode() << 32)).GetHashCode();
Редактирование: Забыл пустые указатели. Код зафиксирован.
Слишком сложный, и забывает, аннулирует, и т.д. Это используется для вещей как объединение, таким образом, можно сойти с рук что-то как
if (null != str1) {
return str1.GetHashCode();
}
if (null != str2) {
return str2.GetHashCode();
}
//Not sure what you would put here, some constant value will do
return 0;
, Это смещается путем предположения, что str1 вряд ли будет распространен в необычно значительной доле экземпляров.
См. Ответ Джона Скита - бинарные операции вроде ^
не подходят, они часто генерируют конфликтующий хеш!