Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Обычно это сделано при помощи сценария, который пытается выполнить препроцессор на попытке включения файла. В зависимости от того, если препроцессор возвращает ошибку, сценарий обновляет сгенерированный.h файл с соответствующим #define (или #undef). В ударе сценарий мог бы неопределенно походить на это:
cat > .test.h <<'EOM'
#include <asdf.h>
EOM
if gcc -E .test.h
then
echo '#define HAVE_ASDF_H 1' >> config.h
else
echo '#ifdef HAVE_ASDF_H' >> config.h
echo '# undef HAVE_ASDF_H' >> config.h
echo '#endif' >> config.h
fi
А довольно полная платформа для того, чтобы портативно работать с проверками мобильности как это (а также тысячи других) autoconf.
Создайте специальную папку для недостающих заголовков и сделайте ту папку, которая будет искаться в последний раз
(который является compliler конкретный - последний объект во "ВКЛЮЧАЕТ" переменную среды, что-то как этот)
Тогда, если некоторый header1.h может отсутствовать, создайте в той папке тупик
header1.h:
#define header1_is_missing
Теперь можно всегда писать
#include <header1.h>
#ifdef header1_is_missing
// there is no header1.h
#endif
Сам препроцессор не может определить существование файлов, но, конечно, можно использовать среду сборки, чтобы сделать так. Я главным образом знаком с, делают, который позволил бы Вам делать что-то вроде этого в своем make-файле:
ifdef $(test -f filename && echo "present")
DEFINE=-DFILENAME_PRESENT
endif
, Конечно, необходимо было бы найти аналог к этому в других средах сборки как VisualStudio, но я уверен, что они существуют.
У Вас мог быть шаг перед сборкой, выполненный, который генерирует включать файл, который содержит список #defines, которые представляют названия файлов, существующих в текущем каталоге:
#define EXISTS_FILE1_C
#define EXISTS_FILE1_H
#define EXISTS_FILE2_C
Затем включайте тот файл из своего исходного кода, и затем Ваш источник может протестировать эти EXISTS_*
, определяет, чтобы видеть, существует ли файл или нет.
Насколько я знаю, что cpp не имеет директивы относительно существования файла.
Вы могли бы быть в состоянии выполнить это с небольшим количеством справки от Make-файла при использовании того же, делают через платформы. Можно обнаружить присутствие файла в Make-файле:
foo.o: foo.c
if [ -f header1.h ]; then CFLAGS+=-DHEADER1_INC
Как @Greg упоминания Hewgill, можно тогда заставить #includes быть условным выражением:
#ifdef HEADER1_INC
#include <header1.h>
#endif
Другая возможность: заполните каталог где-нибудь с версиями нулевой длины всех заголовков, которые Вы хотите дополнительно включать. Передайте-I аргумент этому каталогу как последний такая опция.
GCC cpp ищет включать каталоги в порядок, если это найдет заголовочный файл в более раннем каталоге, то это будет использовать его. Иначе это в конечном счете найдет файл нулевой длины и будет счастливо.
я предполагаю, что другие cpp реализации также ищут их включать каталоги в определенный порядок.
Мне пришлось сделайте нечто подобное для ОС Symbian. Вот как я это сделал: допустим, вы хотите проверить, существует ли файл "file_strange.h", и вы хотите включить некоторые заголовки или ссылку на некоторые библиотеки в зависимости от наличия этого файла.
сначала создайте небольшой пакетный файл для проверки его существования. файл.
autoconf - это хорошо, но для многих небольших проектов он не подходит.
---------- check.bat
@echo off
IF EXIST [\epoc32\include\domain\middleware\file_strange] GOTO NEW_API
GOTO OLD_API
GOTO :EOF
:NEW_API
echo.#define NEW_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF
:OLD_API
echo.#define OLD_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF
---------- check.bat заканчивается
затем я создал файл gnumake
---------- checkmedialist.mk
do_nothing :
@rem do_nothing
MAKMAKE :
check.bat
BLD : do_nothing
CLEAN : do_nothing
LIB : do_nothing
CLEANLIB : do_nothing
RESOURCE : do_nothing
FREEZE : do_nothing
SAVESPACE : do_nothing
RELEASABLES : do_nothing
FINAL : do_nothing
---------- check.mk заканчивается
включает check.mk файл в вашем файле bld.inf, он ДОЛЖЕН быть перед вашими файлами MMP
PRJ_MMPFILES
gnumakefile checkmedialist.mk
, теперь во время компиляции для файла file_strange_supported.h
будет установлен соответствующий флаг.
вы можете использовать этот флаг в своих файлах cpp или даже в файле mmp
например, в mmp
#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
LIBRARY newapi.lib
#else
LIBRARY oldapi.lib
#endif
и в .cpp
#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
CStrangeApi* api = Api::NewLC();
#else
// ..
#endif