NullPointerException
s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException
. Они наиболее распространены, но другие способы перечислены на странице NullPointerException
javadoc.
Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException
, be:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
В первой строке внутри main
я явно устанавливаю ссылку Object
obj
равной null
. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException
, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)
существуют несколько побочных эффектов к классам, вложенным в классах, что я обычно рассматриваю дефекты (если не чистые антишаблоны).
Позволяют нам вообразить следующий код:
class A
{
public :
class B { /* etc. */ } ;
// etc.
} ;
Или даже:
class A
{
public :
class B ;
// etc.
} ;
class A::B
{
public :
// etc.
} ;
Так:
Как заключение, если исключения (например, вложенный класс близкая часть вложенного класса... И даже тогда...), я не вижу никакой смысл во вложенных классах в нормальном коде, поскольку дефекты перевешивают величинами воспринятые преимущества.
, Кроме того, это пахнет как неуклюжая попытка моделировать пространство имен, не используя пространства имен C++.
На простороне, Вы изолируете этот код, и, если частный, делаете его неприменимым, но от "внешнего" класса...
Профессионалы: Все.
Con: Ничто.
факт является перечислимыми объектами, загрязнит глобальную область видимости:
// collision
enum Value { empty = 7, undefined, defined } ;
enum Glass { empty = 42, half, full } ;
// empty is from Value or Glass?
Ony путем помещения каждого перечисления в различное пространство имен/класс позволит Вам избежать этой коллизии:
namespace Value { enum type { empty = 7, undefined, defined } ; }
namespace Glass { enum type { empty = 42, half, full } ; }
// Value::type e = Value::empty ;
// Glass::type f = Glass::empty ;
Примечание, что C++ 0x определил перечисление класса:
enum class Value { empty, undefined, defined } ;
enum class Glass { empty, half, full } ;
// Value e = Value::empty ;
// Glass f = Glass::empty ;
точно для этого вида проблем.
2008 Visual Studio, кажется, не в состоянии обеспечить intellisense для вложенных классов, таким образом, я переключился на идиому PIMPL в большинстве случаев, где я раньше имел вложенный класс. Я всегда помещал перечисления или в класс, если он используется только тем классом, или вне класса в том же пространстве имен как класс, когда больше чем один класс использует перечисление.
Если Вы помещаете перечисление в класс, или пространство имен, intellisense будет в состоянии дать Вам указания, когда Вы попытаетесь помнить перечислимые имена. Мелочь наверняка, но иногда вопрос мелочей.
Я соглашаюсь с защитой сообщений для встраивания Вашего перечисления в классе, но существуют случаи, где имеет больше смысла не делать это (но, по крайней мере, поместите его в пространство имен). Если несколько классов используют перечисление, определенное в различном классе, то те классы непосредственно зависят от того другого реального класса (который владеет перечислением). Это, конечно, представляет недостаток дизайна, так как тот класс будет ответственен за то перечисление, а также другие обязанности.
Так, да, встраивают перечисление в класс, если другой код только использует то перечисление для взаимодействия через интерфейс непосредственно с тем реальным классом. Иначе найдите, что лучшее место сохраняет перечисление, такое как пространство имен.
Для меня большой довод "против" к наличию снаружи случается так, что это становится частью глобального пространства имен. Если перечисление или связанный класс только действительно относятся к классу, в котором это находится, то это имеет смысл. Таким образом в случае принтера, все, что включает принтер, будет знать о наличии полного доступа к перечислимому PRINTER_TYPE, где это не должно действительно знать об этом. Я не могу сказать, что когда-либо использовал внутренний класс, но для перечисления, это кажется более логичным для держания его внутри. Как другой плакат указал, это - также хорошая идея использовать пространства имен для группировки подобных объектов, начиная с засорения глобального пространства имен может действительно быть плохая вещь. Я ранее работал над проектами, которые являются крупными и просто поднимают, автоматический полный список на глобальном пространстве имен занимает 20 минут. По-моему, вложенные перечисления и namespaced классы/структуры являются, вероятно, самым чистым подходом.
paercebal сказал все, что я скажу о вложенных перечислениях.
WRT вложил классы, мой общий и почти единственный вариант использования для них - когда у меня есть класс, который управляет определенным типом ресурса, и мне нужен класс данных, который представляет что-то характерное для того ресурса. В Вашем случае output_tray мог бы быть хорошим примером, но я обычно не использую вложенные классы, если класс будет иметь какие-либо методы, которые будут названными снаружи содержания класса, или больше, чем, прежде всего, класс данных. Я обычно также не вкладываю классы данных, если на содержавший класс непосредственно никогда не ссылаются вне содержания класса.
Так, например, если у меня был printer_manipulator класс, он мог бы иметь содержавший класс для ошибок управления принтером, но сам принтер будет не содержавшим классом.
Hope это помогает.:)
Кажется, что необходимо использовать пространства имен вместо классов для группировки как вещи, которые связаны друг с другом таким образом. Один довод "против", который я видел в выполнении вложенных классов, является Вами, заканчиваются с действительно большим исходным файлом, который мог быть трудным к grok, когда Вы ищете раздел.
Если Вы никогда не собираетесь быть использованием зависимого класса ни для чего кроме работы с реализациями независимого класса, вложенные классы прекрасны, по-моему.
Это - когда Вы хотите использовать "внутренний" класс в качестве объекта самостоятельно, что вещи могут начать становиться немного гадкими, и необходимо начать писать стандартные программы экстрактора/вставки. Не симпатичная ситуация.
Один довод "против", который может стать грандиозным предприятием для крупных проектов, - то, что невозможно сделать предописание для вложенных классов или перечислений.