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

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

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

Author24 — интернет-сервис помощи студентам
Добрый вечер. Объясните пожалуйста, почему в локальном классе могут использоваться только финальные переменные или переменные которые были инициализированы при объявлении (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...

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

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

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

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

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

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

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

То что переменная должна быть final или effectively final как раз таки техническое ограничение. Переменная захватывается по ссылке, а примитив соответственно по значению. Это делается для того что бы метод и локальный класс оперировали одним и тем же значением. При этом то что объект в стеке не мешает использовать его в локальном классе, ссылка и есть ссылка, а объект соберется коллектором потом, когда на него перестанут ссылаться.
0
345 / 141 / 51
Регистрация: 02.12.2015
Сообщений: 333
27.08.2016, 04:47 7
Цитата Сообщение от 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 8
Цитата Сообщение от 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 9
http://csharpindepth.com/Artic... sures.aspx
0
LeX
29.08.2016, 12:38
  #10

Не по теме:

xoraxax, C#?

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

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

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

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

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

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

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Книги и учебные ресурсы по C#
InfoMaster 08.01.2025
Базовые учебники и руководства Одной из лучших книг для начинающих является "C# 10 и . NET 6 для начинающих" Эндрю Троелсена и Филиппа Джепикса . Книга последовательно раскрывает основные концепции. . .
Что такое NullReferenceEx­ception и как исправить?
InfoMaster 08.01.2025
NullReferenceException - одно из самых распространенных исключений, с которым сталкиваются разработчики на C#. Это исключение возникает при попытке обратиться к членам объекта (методам, свойствам или. . .
Что такое Null Pointer Exception (NPE) и как это исправить?
InfoMaster 08.01.2025
Null Pointer Exception (NPE) - это одно из самых распространенных исключений в Java, которое возникает при попытке использовать ссылку на объект, значение которой равно null. Это исключение относится. . .
Русский язык в консоли C++
InfoMaster 08.01.2025
При разработке программ на C++ одной из частых проблем, с которой сталкиваются русскоязычные программисты, является корректное отображение кириллицы в консольных приложениях. Эта проблема особенно. . .
Telegram бот на C#
InfoMaster 08.01.2025
Разработка ботов для Telegram стала неотъемлемой частью современной экосистемы мессенджеров. C# предоставляет мощный и удобный инструментарий для создания разнообразных ботов, от простых. . .
Использование GraphQL в Go (Golang)
InfoMaster 08.01.2025
Go (Golang) является одним из наиболее популярных языков программирования, используемых для создания высокопроизводительных серверных приложений. Его архитектурные особенности и встроенные. . .
Что лучше использовать при создании класса в Java: сеттеры или конструктор?
Alexander-7 08.01.2025
Вопрос подробнее: На вопрос: «Когда одновременно создаются конструктор и сеттеры в классе – это нормально?» куратор уточнил: «Ваш класс может вообще не иметь сеттеров, а только конструктор и геттеры. . .
Как работать с GraphQL на TypeScript
InfoMaster 08.01.2025
Введение в GraphQL и TypeScript В современной разработке веб-приложений GraphQL стал мощным инструментом для создания гибких и эффективных API. В сочетании с TypeScript, эта технология. . .
Счётчик на базе сумматоров + регистров и генератора сигналов согласования.
Hrethgir 07.01.2025
Создан с целью проверки скорости асинхронной логики: ранее описанного сумматора и предополагаемых fast регистров. Регистры созданы на базе ранее описанного, предполагаемого fast триггера. То-есть. . .
Как перейти с Options API на Composition API в Vue.js
BasicMan 06.01.2025
Почему переход на Composition API актуален В мире современной веб-разработки фреймворк Vue. js продолжает эволюционировать, предлагая разработчикам все более совершенные инструменты для создания. . .
Архитектура современных процессоров
inter-admin 06.01.2025
Процессор (центральный процессор, ЦП) является основным вычислительным устройством компьютера, которое выполняет обработку данных и управляет работой всех остальных компонентов системы. Архитектура. . .
История создания реляционной модели баз данных, правила Кодда
Programming 06.01.2025
Предпосылки создания реляционной модели В конце 1960-х годов компьютерная индустрия столкнулась с серьезными проблемами в области управления данными. Существовавшие на тот момент модели данных -. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru