Проблеми TypeScript у світі React-додатків вiд Iллi Климова на React fwdays | 27 березня
×Закрыть

[Java] Декларация static поля во внутреннем классе — ошибка

Сабж, ребята. Объясните подробно, почему нельзя объявлять статическую переменную во внутреннем (не статическом) классе?

в интернете нашёл несколько ответов, но ничего толком не объясняется. С чем связана проблема?

Спасибо.

👍НравитсяПонравилось0
В избранноеВ избранном0
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Интересно, если джуниор не ответит подробно на этот вопрос на собеседовании, его выгнонят с позором?

Интересно, если джуниор не ответит подробно на этот вопрос на собеседовании, его выгнонят с позором?

Джуниора — ДА, синьору — не каждый рискнет задать такой бредовый вопрос.

Я бы тут же («раскрошил в руке печеньку и бросил бы крошки» || «сделал глоток кофе и плюнул бы») в лицо интервьюэру :)

инстанс внутреннего нестатического класса «принаджлежит» инстансу внешнего класса, соответственно вы можете работать только с new Outer().new Inner():
— работать со статик полями/методами через инстансы а не через классы — неправильно и без внутренних классов.

— я подозреваю что запрет связан с реализацией хранения всего в памяти.... static поля/методы хранятся в static секции, non-static в heap/stack, поскольку non-static Inner связан именно с инстансом Outer а не с классом/класслоадером, то скорее всего есть необходимость хранить все что связано с Inner тоже в heap/stack.

наврядле тут есть ограничение из-за памяти. Inner класс может быть пронаследован от другого класса у которого есть статические поля.

статические поля не наследуются, так что это ничего не меняет

ТЕХНИЧЕСКИЕ ТЕМЫ НА ДОУ!? НЕУЖЕЛИ!

«103 комментария» — нет, все в порядке. Нормальный, качественный флуд.

Проблемы нет, в .Net это можно делать.

Тут скорее всего логическое ограничение от авторов Java. Они специально ввели понятие Внутренний («Inner») класс. И сказали, что объект этого типа может быть создан только объектом типа внешнего класса. То есть что бы иметь доступ к интерфейсу внутреннего класса, необходимо для начала иметь экземляр внешнего класса, который сможет создать экземлпяр внутреннего. Ведь экземляр внутреннего класса всегда знает экземляр своего внешнего класса.

Чуть путано — но надеюсь понятно.

Я не большой специалист по Java, вывод сделал прочитав документацию. И повтыкав в след пример:

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);
}

}

Отсюда получается «коллапс» со статическим полем. Которое как бы будет доступно и без экземпляра внешнего класса — ведь поле то статическое. То есть это просто нелогично и не более.

ибо опять таки — нельзя создать экземпляр нестатичного внутреннего класса без экземпляра внешнего класса, но его можно проинициализировать.

Как вариант — могли бы раздрешить только приватные статические поля. Тогда по идее все бы были довольны.

В доке же всё написано, даже с примером кода, освещающим конкретно ваш вопрос. Выбросьте уже своих шилдтов, эккелей и корнеллов, и читайте только первоисточник, за английский же в бодишопах должны «нагибать».

docs.oracle.com/....html#jls-8.1.3 — 8.1.3. Inner Classes and Enclosing Instances

За тему, конечно же, большое спасибо!

Но хотелось бы узнать откуда «ноги растут»: просто интерес или -такой бред- такие тонкости начали на собеседованиях спрашивать?

Однокурсник был озадачен вопросом, сам не спал ночью и другим не давал... всё приходили от него сообщения в скайпе. :))

Однокурсник был озадачен вопросом
А ну тада мона :)
Кстати, а синтаксис создания иннер-классов его не удивил? ИМХО, эпическая странность: создание инстанса выглядит как посылка сообщения.

Пора рассказать ему что ...ить можно не только на мануалы по джаваскрипту

В Джаві є жорстке розділення на static nested classes і non-static nested classes. Non-static nested classes ще інколи називають inner classes, цим самим типу підкреслюється їхня винятковість.

А винятковість inner classes полягає в тому, що вони знаходяться wholly whithin the outer class (тобто суто в рамках його інстансу). А раз так, то і статичні члени в таких inner classes недопустимі.

Але, на мою думку, це все лише додає Джаві сумбуру, при дуже сумнівніній корисності. Треба було:

1) або взагалі не вводити таких жорстких відмінностей між static i non-static(inner) nested classes

2) або якщо є таке велике бажання ці відмінності таки ввести, то напевно варто було придумати якесь специфічне ключове слово для оголошення inner classes. Тобто inner classes мали б оголошуватися не за допомогою ключового слова class, а за допомогою якогось іншого ключогово слова (наприклад innerclass). Чому? Та банально тому що коли я оголошує якусь сутність за допомогою ключового слова class, то я й очікую відповідну поведінку від цієї сутності, і поведінка ця має бути consistent. Чому всі класи дозволяють мені оголошувати всередині них статичні члени, а inner classes не дозволяють? Я ж оголошую inner classes за допомогою того ж самого ключового слова class. Не порядок...

Тому Mizrah Kadima, ваше питання цілком справедливе. Хоча на ньому й світ клином не зійшовся. До речі, майте на увазі що в мові програмування C#, озвученої вами проблеми не існує. Там немає такого жорсткого (сумбурного й сумнівнокорисного) розділення між static i non-static nested classes.

Взагалі, порівнюючи суто мови програмування (а не технології в цілому), С# напевно кращий від Джави. Тому вивчаючи Джаву, можете краєм ока поглядати на C#, тим більше що C# і Джава досить близькі. Стосовно деяких аспектів, C# показує те, якою мала б бути Джава.

винятковість inner classes полягає в тому, що вони знаходяться wholly whithin the outer class (тобто суто в рамках його інстансу). А раз так, то і статичні члени в таких inner classes недопустимі.

“А раз так” — высосано из пальца. Какие именно проблемы возникли бы если бы разрешили статические поля в иннер классах?

Уважніше читайте мій коментар:)

Я ніде й не говорив, що виникли б якісь проблеми. Статичні поля не дозволяють напевно тому, що таким чином просто захотіли покращити дизайн мови програмування Java. Тобто корінь проблеми тут в банальному хотінні дизайнерів мови, їхній позиції, баченні тощо. (Це все оформили в концепцію inner classes.)

Але як я вже писав вище, треба було або відмовитися від цієї концепції. Або реалізувати її краще. ІМХО, звичайно.

Та нет, фраза «А раз так» претендует на обозначение причинно следственной связи, и я написал, что такая связь отсутствует.

...суто в рамках його інстансу... => ...а раз так...

Тобто причиною в даному контексті є знаходження inner class суто «в рамках» інстансу the outer class.

Творці Джави захотіли, щоб non-static nested class (i.e., inner class) був жорство прив’язаний до ідеї інстанційовності the outer class. Жорсткість прив’язки очевидно полягає в:
— без інстансу the outer class неможливо створити інстанс inner class

— не дозволяється, щоб inner class мав статичні члени, бо це робило б його класом у занадто широкому понятті цього слова, а нам потрібен клас який не виходить за рамки ідеї інстанційовності, такий собі ерзац-клас

не дозволяється, щоб inner class мав статичні члени, бо це робило б його класом у занадто широкому понятті цього слова, а нам потрібен клас який не виходить за рамки ідеї інстанційовності, такий собі ерзац-клас

Поздравляю, ты мастер демагог 5-го уровня

Логично было бы при создании джавы не делить внутренние классы на статичные и не статичные а создать единый вид.

К статичному члену внутреннего класса обращаться через внешний и внутренний классы:

Outer.Inner.STATIC_FIELD

А к нестатичному соответственно, через экземпляры внешнего и внутреннего класса:

new Outer().new Inner().non_static_field

Но видимо что-то у них не сраслось, поэтому и было принято решение создать два различных вида внутренних классов. Решение не очень красивое, но ничего не поделаешь.

Розділяти внутрішні класи на статичні і нестатичні можна, чому ж ні. Просто не треба в це розділення вкладати щось зайве. Одним словом, різниця між статичністю чи нестатичністю внутрішніх класів має бути такою ж, як і різниця між статичністю чи нестатичністю зовнішніх класів. Ключове слово static для класу повинно означати тільки те, що всі члени цього класу мають бути статичними і нічого більше (незалежно від того, внутрішній це клас чи зовнішній).

Тепер стосовно того, яким чином добре було б доступатися до внутрішніх статичних і нестатичних класів:

1) Якщо ми доступаємося до статичного внутрішнього класу, то це:
Outer.Inner
2) Якщо доступаємося до нестатичного, то це:
new Outer.Inner()

Тепер стосовно того, яким чином добре було б доступатися до членів цих класів:

1) Якщо ми доступаємося до статичного члена статичного внутрішнього класу, то це:
Outer.Inner.member
2) Нестатичних членів у внітрішніх статичних класах бути не може за означенням
статичного класу, тому переходимо до наступного пункту.
3) Якщо доступаємося до статичного члена нестатичного внутрішнього класу, то це:
Outer.Inner.member
4) Якщо доступаємося до нестатичного члена нестатичного внутрішнього класу, то це:
new Outer.Inner().member

До слова, саме такі правила доступу є в C#.

Ключове слово static для класу повинно означати тільки те, що всі члени цього класу мають бути статичними і нічого більше (незалежно від того, внутрішній це клас чи зовнішній).

Чеее??

UPD.

1) Якщо ми доступаємося до статичного члена статичного внутрішнього класу, то це:
Outer.Inner.member
2) Нестатичних членів у внітрішніх статичних класах бути не може за означенням
статичного класу, тому переходимо до наступного пункту.
3) Якщо доступаємося до статичного члена нестатичного внутрішнього класу, то це:
Outer.Inner.member
4) Якщо доступаємося до нестатичного члена нестатичного внутрішнього класу, то це:

new Outer.Inner().member

Просите, вы джава разработчик или это просто ваши фантазии?

Отличие статического (нестед) от не статического (иннер), в основном, в том что иннер имеют -доступ к экземпляру- ссылку на экземпляр.

Я якраз і пишу про те, як в Джаві це могло би (чи мало би) бути:)

А не про те, як в Джаві це насправді є.

як в Джаві це могло би

А еще оно могло бы создавать единорогов.

чи мало би

Стопудов дожно было создавать единорогов :)
Ваши фантазии — это демонстрация не понимания того зачем придумали Иннер-класы.

Слово static тут применено вполне логично, ибо такой класс (нестед) является статическим “ресурсом” и не может обращаться к не статическим ресурсам. Модификаторы доступа и модификатор static — это не зависымые понятия.

А з чого ви взяли, що я не розумію, для чого існують static nested класи?

Боюсь це ваші фантазії.

А от є одна річ, яку якраз ви не розумієте. Ви думаєте, що єдиним способом гарантувати те, що вкладений клас не має доступу до інстансних членів зовнішнього класу — це зробити цей вкладений клас статичним. Ви так думаєте можливо тому, що звикли до Java-style парадигм. А хто сказав, що в даному випадку вони такі вже правильні?

От я й раджу вам звернути увагу на те, як подібні концепції реалізовані в С#. А там вони реалізовані згідно того, що ви називаєте «фантазіями». І думаю, досить вдало.

А з чого ви взяли, що я не розумію, для чого існують static nested класи?

Отсюда:

1) Якщо ми доступаємося до статичного члена статичного внутрішнього класу, то це:
Outer.Inner.member
2) Нестатичних членів у внітрішніх статичних класах бути не може за означенням
статичного класу, тому переходимо до наступного пункту.
3) Якщо доступаємося до статичного члена нестатичного внутрішнього класу, то це:
Outer.Inner.member
4) Якщо доступаємося до нестатичного члена нестатичного внутрішнього класу, то це:

new Outer.Inner().member

А вот что навело вас на мысль:

Ви думаєте, що єдиним

способом гарантувати те, що вкладений клас не має доступу до інстансних членів зовнішнього класу — це зробити цей вкладений клас статичним.

?

От я й раджу вам звернути увагу на те, як подібні концепції реалізовані в С#.

Приведите аналог Inner (non-static Nested) класса в C#.

Предсказание: будет фабрика :)

UPD. Фабрику так же можно «парировать», но слабенько :)

Те, що ви процитували під словом «Отсюда» — це те, як виглядають nested classes в С#. Тому як би не зовсім зрозуміло, про що ви... Позбудьтеся інерції і вийдіть за рамки Java-style парадигм.

А вот что навело вас на мысль

На цю думку мене навело те, про що ви пишете.

В контексті даної розмови, немає такого вже значення, чим буде «inner class» в С# - фабрикою чи слоном. В С# є поняття nested class. Поняття «іnner class», зашитого прямо в синтаксис мови програмування — так, немає. Але дизайн мови програмування С# від того тільки виграв, мені так здається, порівняно з джавішною ситуацією. От це я і намагаюся донести. Я вам там ще десь один коментар на цю тему написав, по-моєму.

Те, що ви процитували під словом “Отсюда” — це те, як виглядають nested classes в С#.

Нет. Вот ваша цитата:

Тепер стосовно того, яким чином добре було б доступатися до членів цих класів:

Давайте таки оперировать фактами:

На цю думку мене навело те, про що ви пишете.

Цитату, ссылку (лучше с объяснениями).

Але дизайн мови програмування С# від того тільки виграв, мені так здається, порівняно з джавішною ситуацією.

Создайте класс (не объект) жестко связанный с конкретным инстансом (не классом) другого класса, то есть иннер-класс (в терминах джавы)

Там немає такого жорсткого (сумбурного й сумнівнокорисного) розділення між static i non-static nested classes.

Там есть только Nested и нет Inner (non-static nested), на сколько я помню. Когда ответят на комментарий dou.ua/...ic/6080/#228806 будет понятнее.

В C# є тільки nested classes. Nested classes бувають і static, i non-static. І різниця між ними така ж, як і між звичайними статичними й нестатисними класами. Взагалі в C# nested classes мало чим відрізняються від звичайних класів. Те, що вони nested, впливає по суті тільки на їх visibility (і спосіб доступу до них, відповідно).

By default, нестатичний вкладений клас в C# не має доступу до інстансу зовнішнього класу. Щоб він мав такий доступ, треба йому явно передати інстанс зовнішнього класу. Тобто в Джаві це відбувається автоматично (завдяки концепції inner classes), в C# це треба робити вручну.

Але якою ціною це відбувається автоматично в Джаві!!! Inner classes нехай і мають доступ до інстансу зовнішнього класу out of the box, але ці inner classes не можна інстанціювати без попереднього інстанціювання їх outer classes (бо behind the scenes має пройти передача Outer.this) + ці inner classes не можуть мати статичних членів (бо вихід за рамки інстанційовності порушив би концепцію того, що inner class є продовження інстансу the outer class).

Але якою ціною це відбувається автоматично в Джаві!!!

але ці inner classes не можна інстанціювати без попереднього інстанціювання їх outer classes

А как вы предлагаете установить ссылку на обект которого не существует?

И более интересный момент:

ці inner classes не можуть мати статичних членів

Судя по тону для вас это недостаток. Поэтому вопрос:

Зачем нужны статические члены? Вообще, кроме костыля с методом майн.

Сутність, оголошена за допомогою ключового слова class, повинна мати якусь нішеву поведінку, а не так, що ця сутність відповідає за одне, друге, третє... десяте (причому тільки тоді, коли її нахилити під кутом 43 градуси над горизонтом).

Отже, в Джаві поведінка сутності сlass, визначеної всередині іншої сутності class, досить сильно відрізняється (being rather counter-intuitive) від поведінок сутностей class, визначених за інших умов. Це наводить на думку про те, що або цю counter-intuitive поведінку треба би було усунути (як це зробили в С#, наприклад). Або якщо існування сутностей з такою поведінкою таки дійсно потрібне (що далеко не факт), то чому б не створити спеціальне ключове слово для визначення таких сутностей. Наприклад, замість слова class можна було б використовувати слово innerclass. Ввівши нове ключове слово, ми би створили нову сутність і перенесли в неї згадану counter-intuitive поведінку. Таким чином ми би отримали не одну, а дві сутності, але кожна з них була б достатньо нішевого, і це привело б до значно кращої дизайну всієї системи (в даному випадку мови програмування).

Отже, в Джаві поведінка сутності сlass, визначеної всередині іншої сутності class, досить сильно відрізняється (being rather counter-intuitive) від поведінок сутностей class, визначених за інших умов.

Например, отличается от языка D :)

Сутність, оголошена за допомогою ключового слова class, повинна мати якусь нішеву поведінку, а не так, що ця сутність відповідає за одне, друге, третє... десяте

А вот еще одно подтверждение того что вы не понимаете того что значат ключевые слова языка Java :)
Оно (слово class) и имеет нишевое поведение — объявляет класс.

Важно понимать, что в джаве внутренний класс создается в контексте объекта, как и остальные члены, то есть нет разницы:

class O {
int i;
class I {}
static int si;
static class SI {}
}

C# же:

class O {
int i;
class I {}
static int si;
}

Почему-то “int i” в контексте экземпляра, а “class I” в контексте класса как и “static int si”.

Это просто 2 разных подхода. подход Java позволил создать концепт иннер-классов. В C# — есть только нестед-классы (по крайней мере обратного мне не продемонстрировали)

Чувак, ти мені з коментаря в коментар пишеш, що я чогось не розумію, але я не бачу жодного підтвердження цьому в твоїх коментарях:) Давай я буду з коментаря в коментар писати, що Земля квадратна, ок?

Основна інформація, яку несуть твої коментарі, є по суті підмножиною тієї інформації, яку несуть мої. Тому я й пропоную тобі вийти за рамки.

Это просто 2 разных подхода. подход Java позволил создать концепт иннер-классов. В C# — есть только нестед-классы (по крайней мере обратного мне не продемонстрировали)

Дивовижної глибини висновок. Хоча з такого висновку я в принципі почав викладення своєї позиції, а ти до такого висновку тільки тепер прийшов.

Я насправді написав тобі кілька глибших речей. Не знаю, може ти їх не читав. Якщо коротко, то моя позиція полягає в тому, що в С# це все загалом менш криво, ніж Джаві. І я приводив там ряд аргументів, з точки зору абстрактного мислення. (Я звичайно може й помиляюся, патенту на істину в мене немає, але я принаймні намагався вести дискусію в конструктивному руслі і говорити про небанальні речі.)

Хоча з такого висновку я в принципі почав викладення своєї позиції,

То есть это ваша “не заганжована думка”:

Але якою ціною це відбувається автоматично в Джаві!!!

добре було б

Далее:

Чувак, ти мені з коментаря в коментар пишеш, що я чогось не розумію, але я не бачу жодного підтвердження цьому в твоїх коментарях:)

dou.ua/...ic/6080/#228896
dou.ua/...ic/6080/#228880

Кстати, хотелось бы услышать как:

Создайте класс (не объект) жестко связанный с конкретным инстансом (не классом) другого класса, то есть иннер-класс (в терминах джавы)

Мої основні тези, які в коментарях місцями більш детально описуються:

1) щодо конкретно того, чому в Джаві inner class не може включати статичні члени, то я думаю, що це тому, що якби було інакше, то концепція inner class була б занадто розмитою (ні риба, ні м’ясо). Тобто вирішили йти вибраним шляхом до кінця, намагалися зробити цю концепцію достатньо чіткою (нішевою).

2) але поведінку, яка мала б реалізовувати концепцію inner class в Джаві засунули в сутність class, для якої ця поведінка не є характерною. Грубо кажучи, сутність class вже мала певну свою нішеву поведінку, а тут до неї додали ще одну чужу нішеву поведінку. В результаті вийшло так, що сутність class перетворилася на занадто сумбурну (на ній стало висіти забагато відповідальностей).

3) я запропонував подивитися в сторону С#, де немає концепції inner class по дефолту. І сказав, що це краще, бо це дозволяє уникнути розмитості сутності class. Сутність клас в С# таким чином має кращу нішевість => profit.

4) як альтернативу попередньому пункту (хоча не факт, що це краще), я запропонував спосіб, за допомогою якого в Джаві можна було б уникнути розмитості сутності class при збереженні концепції inner class.

5) (спеціально для вас, а не як розвиток теми) Я вважаю, що в контексті даної розмови не важливо, як створюються аналоги inner class в С#. Якщо ви вважаєте, що факт зашиття концепції inner class в синтаксис Джави (such syntactic sugar) оправдовує те, що це зумовило сумбурність сутності class, то я з цим не згідний.

А в чому конкретно полягає ваша позиція? І з якими аспектами моєї позиції ви не згідні?

Думаю, що ми могли б поговорити вживу, то це було б більш продуктивно. Світ тісний, може якось зустрінемось. (Хоча конкретно ця тема — це так, на форумі пописати, звичайно.)

А в чому конкретно полягає ваша позиція?

В том что нельзя использовать необдуманно слова типа:

мала б

І з якими аспектами моєї позиції ви не згідні?

Просто:

2) але поведінку, яка мала б реалізовувати концепцію inner class в Джаві засунули в сутність class, для якої ця поведінка не є характерною.

В Джаве все просто, внутренний класс ведет себя так же как и любой другой член класса. И модификатор статик ведет себя аналогично по отношению к внутреннему классу так же как и к члену класса.

де немає концепції inner class по дефолту. І сказав, що це краще, бо це дозволяє уникнути розмитості сутності class.

Якщо ви вважаєте, що факт зашиття концепції inner class в синтаксис Джави (such syntactic sugar)

Вот именно поэтому (обратите внимание на слово «розмитості» и «зашиття концепції») я и повторяю что вы не понимаете того как оно в джаве.
Лично у меня подход в шарпе вызывает куда больше непоняток чем тот который в джаве, но я не пытаюсь говорит что джавовский более правильный (!) или говорить как оно «мало б бути».
Что касается исходного топика, то проблема вот она dou.ua/...ic/6080/#228887

И она не в подходе, а в реализации подхода. И ограничение на статик членов связаны с реализацией: реально класс создается независимо от инстанса внешнего класса, но программист не имеет доступа к нему без инстанса (на форуме сложно это обяснять)

Світ тісний, може якось зустрінемось.

Я обязательно вас узнаю, ведь «instinct» — это однозначный маркер по которому можно узнать человека :)

1) далі я чую про те, що я чогось не розумію. Хоча я так досі й не побачив жодного аргументу з вашого боку. Суцільне переказування якихось істин, з якими я теж згідний. Мені здається, що я намагаюсь вести розмову в досить абстрактній площині, а ви так розмову вести не хочете / не можете.

2) чому той підхід, який є в С#, викликає у вас більше незручностей, ви так і не описали. Я боюсь, що ви міркуєте якимось категоріями, які є суто Java-specific, тому ви просто не можете подивитися на це все зверху.

2)

И ограничение на статик членов связаны с реализацией: реально класс создается независимо от инстанса внешнего класса, но программист не имеет доступа к нему без инстанса (на форуме сложно это обяснять)

Тобто власної відповіді на запитання, з якого власне й почалося все обговорення, у вас теж немає.

(Здається, я зрозумів. У вас і не було власної позиції. І відповіді на основне питання теж не було. Ви просто будь-якою ціною хотіли поговорити про чимось знайомі вам речі. Ви би краще на чомусь конструктивному зосередилися. Це набагато цікавіше:)

Хоча я так досі й не побачив жодного аргументу з вашого боку.

Ваши слова:

зашиття концепції inner class в синтаксис Джави

Так вот, никто не зашивал “концепцию иннер классов” в джаву. Эта “концепция” появилась как “побочный продукт” реализации лексических замыканий в джава. Если бы вы это понимали и понимали семантику модификатора статик (и слова класс), относительно джава, то у вас бы не возникало “размытости”.

Тобто власної відповіді на запитання, з якого власне й почалося все обговорення, у вас теж немає.

А это что:

реально класс создается независимо от инстанса внешнего класса

? Вам, как знатоку джава, надо объяснять когда выполняются статик блоки?

Здається, я зрозумів.

Вы еще один гадатель по аватарке?

Послухайте, ну все, що ви пишете — це вода. Мені просто важко вести з вами розмову по суті. Суть, суть, мені потрібна суть! Де суть в ваших постах? Не копайтеся в якихось деталях, які не мають жодного відношення до суті. Треба абстрагуватися.

От ви пишете:

Так вот, никто не зашивал «концепцию иннер классов» в джаву. Эта «концепция» появилась как «побочный продукт» реализации лексических замыканий в джава.

Це ж просто смішно. Яка різниця, внаслідок чого в Джаві з’явилися inner classes в тому вигляді, в якому вони є? Нехай і сам Ленін їх туди ввів. Має значення тільки те, що вони там є, і є зашитими в синтаксис. Пишеш на Джаві, маєш inner classes out of the box. Тільки цей факт важливий в даному контексті.

Далі ці слова:

реально класс создается независимо от инстанса внешнего класса

? Вам, как знатоку джава, надо объяснять когда выполняются статик блоки?

Я так і не зрозумів, яким чином ці два речення відповідають на запитання, з якого почався топік. Якщо у вас є відповідь, опишіть її чітко (бажано по пунктах: а, б, в і т.д.). Якщо у вас немає відповіді на даний момент, або ви ще думаєте, то так і скажіть. Для чого все це переливання з пустого в порожнє?

Послухайте, ну все, що ви пишете — це вода.

От кто бы говорил :)

Я так і не зрозумів, яким чином ці два речення відповідають на запитання, з якого почався топік.

А любой кто знает что такое статик-блоки и как они работают понял.

Для вас же поясню:

реально класс создается независимо от инстанса внешнего класса

На момент выполнения статик блока иннер-класса у него нет реально ссылки на объект к которому он привязан. Поэтому допускаются только константы времени компиляции (не выполнения).

Яка різниця, внаслідок чого в Джаві з’явилися inner classes в тому вигляді, в якому вони є?

А это я говорил не в контексте топика, а как демонстрацию того почему вы таки ничего не понимаете :)

Так...

Бравада, бравада, бравада... але місцями є якісь зерна суті. Чи правильні вони, це вже інше питання...

На момент выполнения статик блока иннер-класса у него нет реально ссылки на объект к которому он привязан. Поэтому допускаются только константы времени компиляции (не выполнения).

Ок, ваша позиція стосовно питання топіка зрозуміла. Тільки не зовсім ясно, чому ви вважаєте її правильною. Яке відношення статичні дані іннер класу мають до інстансу зовнішнього класу? Без інстансу зовнішнього класу не можна ініціалізувати статичні дані іннер класу? WTF? А як же тоді по-вашому ініціалізуються статичні дані статичного нестед класу?

Тому ваш аргумент, на мою думку, не дієвий. Обмеження на статичність членів в іннер класі, я думаю, є суто логічним. Бо іннер клас за означенням повинен перебувати суто в скоупі інстансу зовнішнього класу. «Суто в скоупі інстансу зовнішнього класу» означає, що кожен інстанс зовнішнього класу має мати свій унікальний екземпляр даних іннер класу, і дані іннер класу не можуть шаритися між різними інстансами зовнішнього класу. От і все. Тобто сама концепція на логічному рівні накладає відповідні обмеження. Нічого більше.

А это я говорил не в контексте топика, а как демонстрацию того почему вы таки ничего не понимаете :)

А я думаю, що ви це говорили, бо в вас є певні труднощі з абстрактним мисленням:) І деяких речей ви просто не розумієте, бо не здатні подивитися на ситуацію зверху.

Без інстансу зовнішнього класу не можна ініціалізувати статичні дані іннер класу?

class A {
int i;
class B {
static int ii = A.this.i; /* от только нима никакога A.this*/
}
}

А як же тоді по-вашому ініціалізуються статичні дані статичного нестед класу?

class A {
static int i;
static class B {
static int ii = A.i; /* от только нима никакога A.this, ну и пох ибо нам нужен только A*/
}
}

Тому ваш аргумент, на мою думку, не дієвий.

Что и подтверждает мое предположение о вашей не компетентности. (см выше) :)

Обмеження на статичність членів в іннер класі, я думаю

Я же просил без фантазий.

“Суто в скоупі інстансу зовнішнього класу” означає, що кожен інстанс зовнішнього класу має мати свій унікальний екземпляр даних іннер класу, і дані іннер класу не можуть шаритися між різними інстансами зовнішнього класу.

И снова вы свои фантазии выдаете за действительность: dou.ua/...ic/6080/#228887

UPD. Кстати доку почитайте и объясните как в вашу “логику” вписывается допустимость компайл-тайм констант в иннер-класах :)

class A {
int i;
class B {
static int ii = A.this.i; /* от только нима никакога A.this*/
}

}

A.this дійсно тут «нима». Та це й абсолютно логічно. Це зовсім не означає, що є якісь фізичні проблеми для введення статичних членів в іннер клас. Так, статичним членом не міг би бути референс на інстансні дані зовнішнього класу, статичні члени ж ініціалізуються в статичному контексті. Але я запросто міг би написати static int ii = 777, чи наприклад static int ii = [якісь статичні дані зовнішнього класу]. В чому проблема? А проблема просто в тому, що це не захотіли дозволяти суто з точки зору дизайну мови програмування, а не через неможливість це реалізувати. І цей аспект дизайну мови оформили в концепцію іннер класів.

Я ж вам кажу, у вас дуже тяжко з абстрактним мисленням. Тому з вами проблемно вести діалог. Ви не вмієте дивитися на ситуацію зверху. Вам треба все розжовувати на якихось деталях, хоча це зовсім не обов’язково. Попросту кажучи, ви не розумієте, що таке число 5, поки вам прямо перед носом не показати 5 морозив чи 5 іграшкок. Те, що 5 — це щось абстрактне і може означати 5 будь-яких предметів, для вас неочевидно. Вам треба ці предмети прямо перед носом показувати. Але я чесно скажу, вже втомився:)

Боюся, що те, на що ви намагалися вказати словами

И снова вы свои фантазии выдаете за действительность:

не має стосунку до нашої з вами розмови. Схоже ви заплутались в тому сумбурі, яким у вашій голові є картина навколишнього світу:)

UPD. Кстати доку почитайте и объясните как в вашу «логику» вписывается допустимость компайл-тайм констант в иннер-класах :)

Прекрасно вписується. А чому б їй не списуватися? Вона ж не суперечить концепції іннер класів.

На цьому все. Працюйте над собою.

Але я запросто міг би написати static int ii = 777, чи наприклад static int ii = [якісь статичні дані зовнішнього класу]. В чому проблема? А проблема просто в тому, що це не захотіли дозволяти суто з точки зору дизайну мови програмування

:)))

Вы доку таки не читали. Повторяю:

UPD. Кстати доку почитайте и объясните как в вашу “логику” вписывается допустимость компайл-тайм констант в иннер-класах :)

То есть:

static final int ii = 777

Вона ж не суперечить концепції іннер класів.

Но “суперечить” вашему определению:

дані іннер класу не можуть шаритися між різними інстансами зовнішнього класу.

Ибо константа (даже компайл-тайм) — это данные иннер-класса. (Это к разговору об абстрактном мышлении)

Я ж вам кажу, у вас дуже тяжко з абстрактним мисленням.

Ололо, снова фантазии. Где факты?? В данном случае ссылки на мои высказывания + правила вывода.

Щодо того, чому саме компайл-тайм константи вписуються в ідею іннер класів (навіть в моєму розумінні концепції іннер класів), то це я думаю тому, що компайл-тайм константа — це сутність, яка де-факто не є однією й тією й ж самою для всіх інстансів іннер класу. Кожен інстанс іннер класу породжує свій екземпляр цієї константи (вона є inlined). Якось так.

то це я думаю тому, що компайл-тайм константа — це сутність, яка де-факто не є однією й тією й ж самою для всіх інстансів іннер класу.

Все, я сдаюсъ! Феерический фантазер! Продолжим когда вы разберетесь в вопросе или я наберусь терпения.

1) З абстрактної точки зори, дискусію про те, чому в Джаві nested класи реалізовані якось сумбурно, з вами провести не вдається. Говорити про загальні речі — це не до вас.

2) Стосовно суто конкретноого питання, з якого й почався топік, ви стверджуєте, що в Джаві описана поведінка є a must, бо по-іншому це реалізувати неможливо. Ви привели кілька аргументів на свою користь. Я їх спростував. Тому в результаті я так і не розумів, чому в Джаві це реалізувати неможливо. Я залишаюсь при своїй думці, яка полягає в тому, що в Джаві таки можливо реалізувати це по-іншому. Просто не захотіли. Бо в розробників мови було інше бачення стосовно того, що краще. Тобто обмеження, про яке ми говоримо, є суто логічним (свідомо накладеним зверху, а не продиктованим проблемами знизу).

Я їх спростував.

Ты абсолютно прав, ты мега крутой ананимус ©

Да, тяжко вам в Java без protected классов.

Да, тяжко вам в Java без protected классов.

Это вы к чему сказали?

тем что в .NET создаешь внутри рабочего класса protected и работаешь с ним только в самом классе и наследниках. А там можно и static переменные делать и что хочешь.

тем что в .NET создаешь внутри рабочего класса protected и работаешь с ним только в самом классе и наследниках.

При чем тут наследование?

Если я правильно помню то в Ц№ нет иннер классов, только нестед (в них, кстати, можно создавать статик переменные).

если создать прайват или протектед нестед класс — то его объекты могут существовать исключительно в интансе внешнего класса. от определения выше это отличается лишь тем, что всё-же такой класс сможет иметь поля типа

от определения выше это отличается лишь тем, что всё-же такой класс сможет иметь поля типа

Такое возможно:

class Outer {
class Inner {
void someInnerMethod() {
Outer.this.someNonStaticMethod(); /* обращение к экземпляру Outer на основе которого был создан Inner*/
} 
}

void someNonStaticMethod() {}
}

?
То что я помню и увидел тут:
msdn.microsoft.com/...0(v=vs.80).aspx
www.codeproject.com/...ed-Classes-in-C

Это Nested (Inner-Static) классы и в них в Java можно создавать static члены.

нет.
теперь кажется всё прояснилось :) или не прояснилось :) можете привести живой пример какой-нибудь?

а то у меня разрыв шаблона :)

можете привести живой пример какой-нибудь?

Живой не могу, ибо код коммерческий и конструкция довольно сложная, если начать урезать то получится то что написал вверху :)

теперь кажется всё прояснилось :) или не прояснилось :)

Тут msdn.microsoft.com/...0(v=vs.80).aspx есть пример где в Nested передается Container, вот для этого и нужны Иннер классы, чтобы связать Нестед класс с конкретным инстансом. В некотором плане — это «синтаксический сахар» для более безопасной архитектуры. Но инструмент тонкий можно просто усложнить себе жизнь.

Для себя нашел одно применение: упрощает (и ускоряет) рефакторинг, когда надо вынести из класса функциональность (не маленькую), но при этом новый класс очень сильно завязан на исходный.

это было бы идентично паблик нестед классу внутри прайват класса, если бы не было запрета на non-nested private class

это было бы идентично паблик нестед классу внутри прайват класса, если бы не было запрета на non-nested private class

Если я вас таки правильно понял, то нет. :)

В общем, основная фишка — наличие ссылки на экземпляр внешнего класса и возможность работать даже с приватными членами (это вторично, ИМХО).

а каким образом вы получаете доступ к членам этого внутреннего класса? это что-то вроде статических методов и полей в рамках экземпляра?

а каким образом вы получаете доступ к членам этого внутреннего класса?

Так же как и к членам других классов.

Еще раз: отличие в том что внутренний класс имеет ссылку на объект внешнего класса, то есть может обращаться на прямую к членам интстанса (объекта) на основе которого был создан.

Как объяснить по другому не знаю, к сожалению.

UPD.

Так же как и к членам других классов.

Так же вы можете его (иннер-класс) инстанциировать вне объекта оутер-класса, но на основе инстанса оутер-класса.

docs.oracle.com/...aOO/nested.html

а в рамках одного внешнего объекта может быть несколько внутренних объектов? если да — то не вижу причин, чтобы не было членов типа (статических в смысле).

не вижу причин, чтобы не было членов типа (статических в смысле).

Есть 2 инстанса внешнего класса. На основании каждого созданы инстансы внутреннего класса. Статические члены будут шарится между всеми экземплярами внутренних классов или только порожденными от одного внешнего? Очень спорная неоднозначность.

Внутренний класс по своей сути такой же, как и класс верхнего уровня. Отличие только в наличии ссылки на экземпляр последнего. Следовательно, статические члены (если бы они могли быть созданы) будут разделяться всеми экземплярами внутренних классов независимо от того, в контексте какого внешнего класса они были созданы.

именно. тип будет инициализироваться в рамках инстанса. соответственно и члены типа будут шарится в рамках инстанса. отказались от этого скорее чтобы не усложнять, а не из-за того, что это не логично

А что религия запрещает в nested класс передать ссылку на родительский?

зато вот такое возможно
public class Outer
{
public class Inner
{
public static int mS_A;
public int m_A;
public Inner(int aA)
{
m_A = aA;
mS_A = aA;
}
}

}

public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Outer.Inner li = new Outer.Inner(1);
MessageBox.Show(li.m_A.ToString());
MessageBox.Show(Outer.Inner.mS_A.ToString());
}

}

А вместо вызова родителя класса по this — у нас есть лямбды.

А что религия запрещает в nested класс передать ссылку на родительский?

И установить связь между инстансами классов Outer и Inner. А надо между инстансом класса Outer и классом Inner. В теории решение из Java более строгое (и логичное) чем из C#.Но, на практике, это вполне приемлемое решение.

И все-таки хотелось бы услышать ответ на:

Да, тяжко вам в Java без protected классов.

Это вы к чему сказали?

Ну дальше понеслась:

А вместо вызова родителя класса по this — у нас есть лямбды.

Дайте определение понятия «лямбда».

И все-таки хотелось бы услышать ответ на:

nested — protected — классов. Тот же Inner можно сделать протектем и создавать его инстансы сможет только Outer с наследниками.

Дайте определение понятия «лямбда».

C# - лямбды

msdn.microsoft.com/...y/bb397687.aspx

Ну тоесть хороший способ создать анонимный метод без класса внутри другого метода с доступом ко всем полям текущего класса.

nested — protected — классов. Тот же Inner можно сделать протектем и создавать его инстансы сможет только Outer с наследниками.

Нет. Ибо то что вы описали — это Nested Class (который в джаве есть :) ), почитайте что такое Inner Class — он совсем для другого.

А дальше чистый троллинг:

C# - лямбды

msdn.microsoft.com/...y/bb397687.aspx

Эмулируется в джаве при помощи нестед, иннер, анонимных класов. При том эмулируется полностью (если нет укажите что именно упущено)

А вот как эмулировать в шарпе поведение джавовских Иннер класов?

А що не зрозумілого? Прочитайте ще раз і подумайте...
Звернення до статичного поля проводиться через ім’я класу, в якому змінна оголошена. При цьому для звернення не потрібний екземпляр цього класу.

Звернення до внутрішнього класу проводиться через екземпляр обрамляючого класу. При цьому наявність екземпляру обрамляючого класу обов’язкова.

Якщо уявити, що декларація статичних полів у внутрішніх класах допустима, то як до них звертатись? Для цього треба було б спочатку створювати екземпляр обрамляючого класу, а потім аж отримувати доступ до статичної змінної внутрішнього класу, що порушує всю ідею статичних змінних.

логично, если предположить, что к статик полям обращаются исключительно через имена классов. однако, статик поле также может использоваться как общее (шаред) хранилище для всех экземпляров класса, и обращаться к нему можно и через объект (инстанс).

Це інший бік static полів. Мені не відразу спадає на думку ідея зрозумілого пояснення причини заборони static в nested класах з цього боку :)

більш-менш зрозумів. Дякую, що пояснили.

Судя по всему, это искусственное ограничение на уровне компиляции. Так как внутренний класс связан с экземпляром основного класса (любой экземпляр внутреннего класса связан с единственным экземпляром внешнего класса, в контексте которого он был создан), и чтобы не вносить излишней путаницы, решили сделать такое ограничение.

Пишуть так:

" модификатор static означает, что данная сущность принадлежит классу, а не экземпляру класса."

Наскільки я зрозумів, пробема в тому, що ти хочеш зробити екземпляр класу, і ізвертатися до статичної змінної цього екзмпляра. А це не логічно.

п.с.
Пишу як Джава початківець, а не гуру, можу і помилятися
апдейт.

А чому статична змінна, у внутрішньому класі, який в цьому сакральний зміст?

Странный вопрос

Попробуй написать обращение к такому полю, и ты сам сразу увидишь почему нельзя.

ответов на “почему” там нет

The field sfield cannot be declared static; static fields can only be declared in static or top level types

© Eclipse

Эм.. Не совсем понял.
Я предлагаю написать не static field, а гипотетическое обращение к нему, если бы вдруг написать его было возможно. Вот как бы оно выглядело?

А чего это ты через инстанс обращаешься? Обратись через класс!

а ты напиши

public static final int x = 5;

а почему не
public static final String z = «10» ?

кто просил константу?

а почему не
public static final String z = “10” ?

кто просил константу?

docs.oracle.com/...ls/se7/jls7.pdf

Вот, Outer.Inner.STATIC_FIELD уже похоже на то, как бы оно могло выглядеть.
Только так написать нельзя, и вовсе не из-за STATIC_FIELD, а раньше: получить доступ к нестатическому Inner можно только через какой-то инстанс Outer.

Выходит, что правильно обратиться к такому филду просто невозможно, и это собственно и есть то самое «почему» его нельзя объявить.

пример:

public class OuterTest {
public InnerTest innerInstance;
OuterTest(){ // constructor
innerInstance = new InnerTest();
}
public class InnerTest {
public int field = 10;
}
}

public class InstanceTest {
public static void main(String[] args) {
OuterTest outerInstance = new OuterTest();
System.out.println(outerInstance.innerInstance.field);
}
}
А че, в жаве есть такое понятие, как — статические/не статические классы ?
В С++ статический не статический можно применять только к
— глобальным объектам

— методам / членам класса

Слово static может вводить в заблуждение. Оно вовсе не означает, что мы не можем инстанциировать этот класс. На самом деле статический класс это самый обычный класс, использующий имя внешнего класса наподобие того, как внешний класс использует имя пакета.

Outer.Inner i = new Outer.Inner();

Статический класс не имеет доступа к членам внешнего класса (кроме статических) и вообще никак с ним не связан, за исключением имени.

Есть

В жаве членом класса может (кроме полей и методов) быть еще и класс (внутренний). И он, как и другие члены класса, может быть статическим или не статическим.

Ага, class {} может объявляться в interface(ах) и автоматически принимать модификаторы public static. И называется такой класс «вложенный». :)

С++ другой язык. Давайте не отходить от темы. :)

Не дай Бог спеціаліст, який буде проводити зі мною співбесіду не знатиме цього, не зможе пояснити і не зможе розібратись в документації...

...и что будет? Вы уволитесь с компании? :D

Вы устройте срез знаний в своей компании, я думаю, окажется много специалистов, которые что-то забыли, что-то не знали, а что-то будут не способны объяснить.

Скажу щоб пішов тренуватись на співбесідах через скайп. Може й кілька корисних лінків йому пораджу, наприклад dou.ua/...ums/topic/6072

Не дай же бог этому случиться... Аж страшно представить, что в таком случае будет...

внутренний класс ассоциируется конкретно с экземпляром обрамляющего класса

Можете объяснить подробно... показать примеры? Лично я воспринимаю это просто как факт. Нельзя — нельзя...

Например, если мы пишем new MyClass().staticField, то программа все равно будет обращаться к статическому полю через MyClass.staticField. А как бы это выглядело в случае внутреннего класса? MyOuterClass.MyInnerClass.staticField — чувствуется неловкость ситуации, ведь внутренний класс не завязан ни на какой экземпляр внешнего класса

так обращение к статик полю идет через имя экземпляра внешнего класса и имени внутреннего класса? Для разных экземпляров внешнего класса статик поле как бы разное, но для внутреннего класса статик поле все равно одно. Почему же компилятор не допускает?

тоже не совсем понял вопрос, но вы вот сами написали, что «для разных экземпляров внешнего класса статик поле как бы разное», а получить доступ к внутреннему классу можно только через экземпляр внешнего класса.

то-есть в Джаве можно обратиться через инстанс к переменной типа?

а почему во внешнем классе по-вашему была бы нелогична конструкция вроде этой

MyInnerClass.staticField

?

Нельзя_просто_так_взять_и_задекларировать_static_поле_во_внутреннем_классе.джпг :)

stackoverflow.com/...n-inner-classes

к слову, внутренние классы имеют полноценный доступ к полям внешнего класса, что мешает определить статическое поле не внутри внутреннего класса, а вне?

Да, я видел эти ответы, но так ничего и не понял. Можете на русском языке объяснить? Интересует не сам факт, а следствие.

Спасибо.

насколько я понял, нестатические внутренние классы завязаны на инстансы, и поэтому не очевидно, будет ли данное поле статическим лишь внутри текущего инстанса внешнего класса, или оно является статическим глобально. возможно также, физическое распределение (в разные области памяти) описательных объектов классов, статических данных и инстансов внутри JVM накладывает это ограничение как технологическое.

Вообще-то, JVM никак не отличает внутренние классы и классы высшего уровня. Для нее они все одинаковые.

нет там ограничений из-за дизайна JVM. (тоже но с словом final разрешено), скорей это логическое ограничение, которое не дает кривым рукам писать плохой код.

Подписаться на комментарии