Другое событие 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));
}
Что происходит, здесь назван агрегат инициализация. Вот является (сокращенное) определение агрегата от раздела 8.5.1 из спецификации ISO:
агрегат является массивом или классом без объявленных пользователями конструкторов, никакого частного или защитил нестатические элементы данных, никакие базовые классы и никакие виртуальные функции.
Теперь, с помощью {0}
для инициализации агрегата как это в основном прием к 0
вся вещь. Это вызвано тем, что при использовании совокупной инициализации Вы не должны определять всех участников , и спецификация требует, чтобы все неуказанные участники были инициализированным значением по умолчанию, что значит набор для 0
для простых типов.
Вот соответствующая кавычка от спецификации:
, Если в агрегате существует меньше инициализаторов в списке, чем, существуют участники, то каждый участник, не явно инициализированный, должен быть инициализирован значением по умолчанию. Пример:
struct S { int a; char* b; int c; }; S ss = { 1, "asdf" };
инициализирует
ss.a
с1
,ss.b
с"asdf"
, иss.c
со значением выражения формыint()
, то есть,0
.
можно найти полную спецификацию по этой теме здесь
Одна вещь знать состоит в том, что эта техника не обнулит дополнительные байты. Например:
struct foo
{
char c;
int i;
};
foo a = {0};
Не то же как:
foo a;
memset(&a,0,sizeof(a));
В первом случае, дополните байты между c, и я являюсь неинициализированным. Почему Вы заботились бы? Ну, если Вы сохраняете эти данные на диск или отправляете их по сети или что бы то ни было, у Вас могла бы быть проблема безопасности.
Обратите внимание, что также работает пустой совокупный инициализатор:
SHELLEXECUTEINFO sexi = {};
char mytext[100] = {};
Я также использую его для инициализации строк, например,
char mytext[100] = {0};
Это было некоторое время, так как я работал в c/c ++, но IIRC, тот же ярлык может использоваться для массивов также.
In answer to why ShellExecuteEx()
is crashing: your SHELLEXECUTEINFO
"sexi" struct has many members and you're only initializing some of them.
For example, the member sexi.lpDirectory
could be pointing anywhere, but ShellExecuteEx()
will still try to use it, hence you'll get a memory access violation.
When you include the line:
SHELLEXECUTEINFO sexi = {0};
before the rest of your structure setup, you're telling the compiler to zero out all structure members before you initialize the specific ones you're interested in. ShellExecuteEx()
knows that if sexi.lpDirectory
is zero, it should ignore it.