Я не думаю, что реальная разница стала ясной в вышеупомянутых ответах.
Сначала разобраться в условиях:
Ответ Martin является правильным до сих пор. Однако фактический вопрос: Что цель объявить вложенный статичный класс или нет?
Вы используете статические вложенные классы, если Вы просто хотите держать свои классы вместе, если они принадлежат актуально вместе или если вложенный класс исключительно используется в классе включения. Нет никакого семантического различия между статическим вложенным классом и любым классом.
Нестатические вложенные классы являются другим зверем. Подобный анонимным внутренним классам, такие вложенные классы являются на самом деле закрытиями. Это означает, что они получают свой окружающий объем и свой экземпляр включения и делают это доступным. Возможно, пример разъяснит это. Посмотрите этот тупик Контейнера:
public class Container {
public class Item{
Object data;
public Container getContainer(){
return Container.this;
}
public Item(Object data) {
super();
this.data = data;
}
}
public static Item create(Object data){
// does not compile since no instance of Container is available
return new Item(data);
}
public Item createSubItem(Object data){
// compiles, since 'this' Container is available
return new Item(data);
}
}
В этом случае Вы хотите иметь ссылку от дочернего объекта до родительского контейнера. Используя нестатический вложенный класс, это работает без некоторой работы. Можно получить доступ к экземпляру включения Контейнера с синтаксисом Container.this
.
Больше жесткого следующего объяснений:
При рассмотрении байт-кодов Java, компилятор генерирует для (нестатического) вложенного класса, это могло бы стать еще более ясным:
// class version 49.0 (49)
// access flags 33
public class Container$Item {
// compiled from: Container.java
// access flags 1
public INNERCLASS Container$Item Container Item
// access flags 0
Object data
// access flags 4112
final Container this$0
// access flags 1
public getContainer() : Container
L0
LINENUMBER 7 L0
ALOAD 0: this
GETFIELD Container$Item.this$0 : Container
ARETURN
L1
LOCALVARIABLE this Container$Item L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 1
public <init>(Container,Object) : void
L0
LINENUMBER 12 L0
ALOAD 0: this
ALOAD 1
PUTFIELD Container$Item.this$0 : Container
L1
LINENUMBER 10 L1
ALOAD 0: this
INVOKESPECIAL Object.<init>() : void
L2
LINENUMBER 11 L2
ALOAD 0: this
ALOAD 2: data
PUTFIELD Container$Item.data : Object
RETURN
L3
LOCALVARIABLE this Container$Item L0 L3 0
LOCALVARIABLE data Object L0 L3 2
MAXSTACK = 2
MAXLOCALS = 3
}
Поскольку Вы видите, что компилятор создает скрытое поле Container this$0
. Это установлено в конструкторе, который имеет дополнительный параметр Контейнера типа для определения экземпляра включения. Вы не видите этот параметр в источнике, но компилятор неявно генерирует его для вложенного класса.
Пример Martin
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
был бы так скомпилирован в вызов чего-то как (в байт-кодах)
new InnerClass(outerObject)
Ради полноты:
Анонимный класс является идеальным примером нестатического вложенного класса, который просто не имеет никакого имени, связанного с ним, и не может быть сослан позже.
Вот пример настройки всего, что выбрано в {}
В инструментах, диспетчере кодов.
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>{}</Title>
<Shortcut>{}</Shortcut>
<Description>Code snippet for {}</Description>
<Author>Sérgio</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Code Language="csharp"><![CDATA[{
$selected$ $end$
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
У меня есть для вас пример. Этот фрагмент окружает выделенный текст
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<Header>
<Title>Surround in CDATA</Title>
<Author>Sten Hougaard, 2010 - http://www.netsi.dk/wordpress</Author>
<Shortcut>shortcut</Shortcut>
<Description>Surrounds selected data in CDATA</Description>
<SnippetTypes>
<SnippetType>SurroundsWith</SnippetType>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>name</ID>
<Default>value</Default>
</Literal>
</Declarations>
<Code Language="XML">
<![CDATA[<![CDATA[$selected$]]><![CDATA[]]]><![CDATA[]]]><![CDATA[>]]>
</Code>
</Snippet>
</CodeSnippet>
Шаги для создания этого примера следующие:
Теперь фрагмент готов к использованию. Попробуйте использовать соответствующий сценарий, например файл XML. Выделите данные и нажмите Ctrl + K и Ctrl + S (или пройдите через меню). Найдите фрагмент и вуаля - ваши данные окружены CDATA.