Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
1 / 1 / 0
Регистрация: 20.04.2015
Сообщений: 73

Почему в локальном классе доступны финальные переменные или переменные инициализированные при объявлении

26.08.2016, 03:38. Показов 5666. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер. Объясните пожалуйста, почему в локальном классе могут использоваться только финальные переменные или переменные которые были инициализированы при объявлении (effectively final). Почему в локальном классе нельзя использовать обычные переменные, т.е. изменяемые ??

Спасибо !!!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.08.2016, 03:38
Ответы с готовыми решениями:

Turbo Pascal и инициализированные переменные
const s: String='389595742'; var i: Integer; begin for i:=Length(s) downto 1 do if Odd(i) then Delete(s,i,1); for i:=1 to...

Среднее арифметическое, не видит инициализированные переменные
Привет, ребят! Есть программа- вычисление среднее арифм. чисел от 1 до 5000. Проверка на принадлежность границе вынесена в отдельную...

ООП: почему переменные в классе обозначают именно так?
Подскажите почему переменые в классе обозначают так class MyClass { var $a; public var $b; } Почему пишеться var...

21
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
26.08.2016, 08:01
https://docs.oracle.com/javase... asses.html
1
 Аватар для Lumber
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
26.08.2016, 12:08
Это относится только к переменным объявленным вне локального класса.

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

Фактически в локальный класс передаются значения внешних локальных переменных, а не сами переменные. В случае неизменяемых переменных это различие не играет роли, а значит и не приводит к ошибкам.
1
1 / 1 / 0
Регистрация: 20.04.2015
Сообщений: 73
26.08.2016, 23:58  [ТС]
xoraxax, т.е. локальный класс захватывает переменную, а почему он не делает копию этой переменной ? или
внутреннюю скрытую ссылку на эту переменную ? (что-то вроде лямда-функции в C++11, которая может захватить переменную по ссылке или по значению).
И все же непонятно, почему локальный класс не может захватить эту переменную после какого-нибудь изменения, т.е. почему должна быть именно effectively final?
0
 Аватар для Lumber
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
27.08.2016, 02:10
Локальный класс именно делает копию с захватываемой переменной.
А запрет на её изменение искусственный, и не имеет "технической необходимости". Зачем он введён - я своё предположение написал выше.

Захват ссылки на локальную переменную я сомневаюсь что можно сделать в Java. Она же в стеке находится и исчезнет когда метод завершится. А ссылка останется, и что будет? Во-вторых в Java вообще нет ссылок на стек.
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
27.08.2016, 03:29
Lumber, ты пишешь абсолютно неверные вещи, не надо человеку высказывать догадки не основываясь на фактических данных, тем более по приведенной выше ссылке все понятно черным по белому написано.

То что переменная должна быть final или effectively final как раз таки техническое ограничение. Переменная захватывается по ссылке, а примитив соответственно по значению. Это делается для того что бы метод и локальный класс оперировали одним и тем же значением. При этом то что объект в стеке не мешает использовать его в локальном классе, ссылка и есть ссылка, а объект соберется коллектором потом, когда на него перестанут ссылаться.
0
 Аватар для Lumber
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
27.08.2016, 04:47
Цитата Сообщение от LeX BB Посмотреть сообщение
При этом то что объект в стеке не мешает использовать его в локальном классе, ссылка и есть ссылка, а объект соберется коллектором потом, когда на него перестанут ссылаться.
В java не может быть объектов в стеке. И сборщик мусора в стеке ничего не убирает. В стеке только примитивы и ссылки.
Захват ссылки на объект не есть захват объекта.

(В C++ могут быть объекты на стеке и указатели/ссылки на стековые переменные в том числе и примитивные типы, кроме того в C++ в отличии от Java допустима ситуация когда указатель невалиден так что там захват можно организовать по другому)

Цитата Сообщение от LeX BB Посмотреть сообщение
Переменная захватывается по ссылке, а примитив соответственно по значению.
Термин "захватывание" относится только к локальным переменным. А ссылок на локальные переменные в Java не существует в принципе. Захватывается всё по значению.

Цитата Сообщение от LeX BB Посмотреть сообщение
Это делается для того что бы метод и локальный класс оперировали одним и тем же значением.
Это не техническое ограничение (если разрешить менять переменную - ничего не сломается). Это только для
облегчения понимания человеком (ещё возможно это задел на будущее - чтобы оставить возможность внести изменения в язык в будущем - сделать захват по ссылке (?) но я сомневаюсь в технической возможности такого).

Фактически значения переменных захватываются в момент создания экземпляра локального класса.
(можно считать что захватываемые переменные передаются неявно как аргументы в конструктор локального
класса и записываются в его поля).

Но чтобы об этом не приходилось думать просто запретили менять переменные.
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
29.08.2016, 08:26
Цитата Сообщение от Lumber
В java не может быть объектов в стеке. И сборщик мусора в стеке ничего не убирает. В стеке только примитивы и ссылки.
Захват ссылки на объект не есть захват объекта.
Ваш кэп. Я имел ввиду ссылку

Цитата Сообщение от Lumber
Термин "захватывание" относится только к локальным переменным. А ссылок на локальные переменные в Java не существует в принципе. Захватывается всё по значению.

Не по теме:

у дяди Шилдта наверно сердце в это время закололо


парень, в java все по ссылке.

Цитата Сообщение от Lumber
Это не техническое ограничение (если разрешить менять переменную - ничего не сломается). Это только для
облегчения понимания человеком (ещё возможно это задел на будущее - чтобы оставить возможность внести изменения в язык в будущем - сделать захват по ссылке (?) но я сомневаюсь в технической возможности такого).

Lumber, вот тебе must read для освежения знаний. метод имеет внутри себя переменные, которые имеют значения (примитивы) либо ссылки (на объекты). локальные классы, так же как анонимные классы и лямбды, захватывают локальные переменные по ссылке либо по значению для примитивов, т.е. копируют ссылку или значение. в случае с полями родительского класса происходит захват ссылки на экземпляр родительского класса (обращение как ParentClass.this.member), поэтому поля менять можно, а в случае метода нельзя, т.к. у метода нет ссылки и соответственно обратиться как methodName.member нельзя. то же самое касается переменных метода родительского класса

Добавлено через 57 секунд
NewBi, тоже обрати внимание на написанное
1
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
29.08.2016, 10:40
http://csharpindepth.com/Artic... sures.aspx
0
29.08.2016, 12:38

Не по теме:

xoraxax, C#?

а, все, понял)

0
 Аватар для Lumber
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
29.08.2016, 13:44
Цитата Сообщение от LeX BB Посмотреть сообщение
Ваш кэп. Я имел ввиду ссылку
а ссылка захватывается по значению

Цитата Сообщение от LeX BB Посмотреть сообщение
в java все по ссылке.
Захват по ссылке привёл бы к возможности изменять захватываемые переменные. Чего нет.

Собственно ради людей которые этого не понимают и путают ссылку на объект с самим объектом, а захват ссылки с "захватом по ссылке" и было введено требование неизменяемости захватываемых переменных.
1
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
31.08.2016, 09:53
Цитата Сообщение от Lumber
а ссылка захватывается по значению
а я что написал?

Цитата Сообщение от Lumber
Захват по ссылке привёл бы к возможности изменять захватываемые переменные. Чего нет.
захват по ссылке подразумевает что ты захватил(скопировал) ссылку, т.е. знаешь на какую область памяти она указывает, при этом, как я уже говорил, нет ссылок на локальные переменные. поэтому изменение локальной переменной приведет к тому что она будет иметь другую ссылку, т.е. будет указатель на другую область памяти, при этом захваченная локальным классом ссылка останется та же и в итоге получается оперирование разными объектами. поэтому для избежания подобных конфликтов локальные переменные, которые были захвачены, менять запрещается. это собственно и есть техническое ограничение.

Цитата Сообщение от Lumber
Собственно ради людей которые этого не понимают и путают ссылку на объект с самим объектом, а захват ссылки с "захватом по ссылке" и было введено требование неизменяемости захватываемых переменных.
тебе самому надо со всем этим разобраться
1
 Аватар для Lumber
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
31.08.2016, 16:04
Цитата Сообщение от LeX BB Посмотреть сообщение
захват по ссылке подразумевает что ты захватил(скопировал) ссылку,
копирование значения - это захват по значению (даже если это значение является ссылкой).
при захвате по ссылке копируется не значение, а ссылка на это значение.
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
31.08.2016, 17:48
Цитата Сообщение от Lumber
при захвате по ссылке копируется не значение, а ссылка на это значение.
кэп, а я о чем говорю?
0
1 / 1 / 0
Регистрация: 20.04.2015
Сообщений: 73
01.09.2016, 13:03  [ТС]
Цитата Сообщение от LeX BB Посмотреть сообщение
поэтому изменение локальной переменной приведет к тому что она будет иметь другую ссылку, т.е. будет указатель на другую область памяти, при этом захваченная локальным классом ссылка останется та же и в итоге получается оперирование разными объектами.
Можно же захватить как read-only. Вот например в C++, лямбда функция может захватить переменную по значению, но тогда эту переменную менять нельзя, можно просто использовать значение этой переменной в теле лямбды.
Вот пример:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
int a = 10;
a = 15;  // меняем значение переменной.
 
auto func = [=]()
{
a = 11;  // ошибка, захват по значению, менять нельзя, можно просто использовать.
std::cout<<a<<std::endl;
}
 
func();
 
auto func2 = [&]()
{
a = 11;  // а тут нет ошибки, захват переменной по ссылке.
std::cout<<a<<std::endl;
}
 
func2();
...
Т.е. "a" является переменной не effectively final, и спокойно происходит ее захват.
Я не понимаю вот этой необходимости в effectively final переменной. Почему не может работать как в первом примере?
0
 Аватар для Lumber
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
01.09.2016, 14:16
Цитата Сообщение от NewBi Посмотреть сообщение
Можно же захватить как read-only.
Да, даже можно было бы и не read-only сделать. Это тоже искусственное ограничение в C++.

Это просто две разные переменные с одинаковыми именами, которые ничто не мешает (кроме правил языка) менять независимо.
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
02.09.2016, 09:18
Цитата Сообщение от Lumber
искусственное ограничение
раз это так и ты знаешь как сделать - реши проблему и создай пул реквест в java, опенсорс все-таки.
ну и в комюнити c++ можешь еще рассказать как реализовать, поучить людей так сказать) а то сидят тупые, сделать не могут)
0
 Аватар для Lumber
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
02.09.2016, 16:03
Это вопрос не реализации, а стандарта языка.
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
02.09.2016, 19:55
Ну ок, стань участником JCP сначала)
0
0 / 0 / 0
Регистрация: 11.12.2018
Сообщений: 1
12.12.2018, 10:39
Область видимости локальных переменных в джаве это метод, конструктор или блок в котором объявлена эта переменная (+ их внутрянки).
Спецификация языка гарантирует, что эти переменные не могут изменять вне области видимости.
Блок может "помереть", а локальный класс, объявленный в этом блоке, можно передать еще кому-нибудь. Поэтому значения этих переменных "прошиваются" в этом классе во время его объявления.
Чтобы поддерживать спецификацию (нельзя изменять вне блока) и как-бы "имитировать" что в локальном классе и в блоке одна и таже переменная - эти локальные переменные должны не изменяться - быть финал или эффективити финал.
Чтобы в этих переменных был какой-нибудь смысл они должны быть инициализированы до создания локального класса.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.12.2018, 10:39
Помогаю со студенческими работами здесь

Одинаковые переменные в одном методе, классе или функции
Здравствуйте. Читаю JavaRush. Написано - - Нельзя создать две переменных с одинаковыми именами в одном методе. А в разных...

Не доступны переменные с запросом
Добрый день. Подскажите в чем может быть проблема: у меня есть запрос, который помещен в переменную. Если нажата кнопка - передается...

Почему при объявлении переменных в классе просит фигурную скобку в конце?
package main; public class Optimizacia { class x { double x=0, eps=0, fx=0, pfx=0, ppfx=0; x=5; eps=Math.pow(10,...

Переменные из процедуры доступны в главной функции
Добрый вечер. Друг мне дал процедуру: void multm(int a, int b, int result) { int i, j, i1; for (i=0; i&lt;3; i++) { ...

Ошибка "переменные ans_hour ans_minute и ans_second не инициализированные"
П.5.4. Правил Запрещено создавать темы с бессмысленными названиями вроде &quot;Помогите!&quot;, &quot;Вопрос&quot; и т.п. &quot;Опять...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru