Я читаю книгу о Java, и там говорится, что вы можете объявить весь класс как final
. Я не могу думать ни о чем, где бы я использовал это.
Я просто новичок в программировании, и мне интересно, действительно ли программисты используют это в своих программах . Если они это сделают, то когда они используют это, чтобы я мог лучше понять это и знать, когда его использовать.
Если Java является объектно-ориентированным, и вы объявляете класс final
, разве это не останавливает идею класса, имеющего характеристики объектов?
В Java элементы с
final
модификатором не могут быть изменены!Это включает в себя финальные классы, финальные переменные и финальные методы:
источник
final
модификатором не могут быть изменены!» Слишком категорично и, на самом деле, не совсем правильно. Как сказал Грэди Буч: «Объект имеет состояние, поведение и идентичность». Хотя мы не можем изменить идентификатор объекта после того, как его ссылка была помечена как окончательная, у нас есть шанс изменить его состояние , назначив новые значения его неполеfinal
(при условии, конечно, что они есть). Любой, кто При планировании получения Oracle Java Certification (например, 1Z0-808 и т. д.) следует помнить об этом, поскольку на экзамене могут возникнуть вопросы по этому аспекту ...Один сценарий, в котором важен final, когда вы хотите предотвратить наследование класса по соображениям безопасности. Это позволяет вам убедиться, что выполняемый вами код не может быть переопределен кем-либо.
Другой сценарий для оптимизации: мне кажется, я помню, что компилятор Java включает некоторые вызовы функций из конечных классов. Итак, если вы вызываете
a.x()
и объявляется afinal
, мы знаем во время компиляции, каким будет код, и можем встроить его в вызывающую функцию. Я понятия не имею, действительно ли это сделано, но с финалом это возможно.источник
Лучший пример
который является неизменным классом и не может быть расширен. Конечно, это нечто большее, чем просто сделать финал класса неизменным.
источник
Соответствующее чтение: принцип Открытого и закрытого Боба Мартина.
Ключевая цитата:
final
Ключевым словом является средством для обеспечения соблюдения этого в Java, будь то используется на методах или классы.источник
final
делает класс закрытым для расширения, а не открытым? Или я воспринимаю это слишком буквально?final
объявления класса / метода не имеет смысла, если вы хотите, чтобы код реализации был закрыт для модификации, но открыт для расширения посредством наследования.Если вы представляете иерархию классов как дерево (как в Java), абстрактные классы могут быть только ветвями, а конечные классы - это те, которые могут быть только листами. Классы, которые не попадают ни в одну из этих категорий, могут быть как ветвями, так и листами.
Здесь нет нарушения принципов ОО, финал просто обеспечивает хорошую симметрию.
На практике вы хотите использовать final, если хотите, чтобы ваши объекты были неизменяемыми, или если вы пишете API, чтобы сигнализировать пользователям API о том, что класс просто не предназначен для расширения.
источник
Само ключевое слово
final
означает, что что-то является окончательным и не должно быть изменено каким-либо образом. Если класс помечен,final
он не может быть расширен или подклассифицирован. Но вопрос в том, почему мы отмечаем классfinal
? ИМО есть разные причины:Я слышал, что класс маркировки
final
повышает эффективность, но, честно говоря, я не мог найти этот аргумент, чтобы иметь большой вес.Возможно, да, но иногда это является целью. Иногда мы делаем это для достижения большей пользы от безопасности и т. Д., Жертвуя способностью этого класса расширяться. Но последний класс все еще может расширять один класс, если это необходимо.
С другой стороны, мы должны предпочесть композицию, а не наследование, и
final
ключевое слово фактически помогает в реализации этого принципа.источник
Будьте осторожны, когда вы делаете класс "выпускной". Потому что, если вы хотите написать модульный тест для финального класса, вы не можете создать подкласс этого финального класса, чтобы использовать технику разрушения зависимостей «Метод подкласса и переопределения», описанную в книге Майкла С. Фезерса «Эффективная работа с устаревшим кодом» , В этой книге Перья сказал: «Серьезно, легко поверить, что запечатанная и окончательная ошибка является ошибочной, что их никогда не следовало добавлять в языки программирования. Но настоящая ошибка лежит на нас. Когда мы напрямую зависим от библиотеки, которые находятся вне нашего контроля, мы просто напрашиваемся на неприятности ".
источник
final class
можно избежать взлома публичного API при добавлении новых методовПредположим, что в версии 1 вашего
Base
класса вы делаете:и клиент делает:
Затем, если в версии 2 вы хотите добавить
method
метод дляBase
:это сломало бы клиентский код.
Если бы мы использовали
final class Base
вместо этого, клиент не смог бы наследовать, и добавление метода не сломало бы API.источник
Если класс помечен
final
, это означает, что структура класса не может быть изменена ничем внешним. Где это наиболее заметно, это когда вы делаете традиционное полиморфное наследование, в основномclass B extends A
просто не сработает. Это в основном способ защитить некоторые части вашего кода (в некоторой степени) .Для пояснения, маркировка класса
final
не помечает его поля какfinal
таковые, и поэтому не защищает свойства объекта, а реальную структуру класса.источник
РЕШЕНИЕ ЗАДАЧИ ЗАКЛЮЧИТЕЛЬНОГО КЛАССА:
Есть два способа сделать урок финальным. Первый - использовать ключевое слово final в объявлении класса:
Второй способ сделать класс final - объявить все его конструкторы как частные:
Отметив его как финальный, вы избавитесь от проблем, если узнаете, что это действительно финал, чтобы продемонстрировать взгляд на этот тестовый класс. выглядит публично на первый взгляд.
К сожалению, поскольку единственный конструктор класса является закрытым, расширить этот класс невозможно. В случае с классом Test нет причин, по которым класс должен быть окончательным. Класс Test является хорошим примером того, как неявные конечные классы могут вызывать проблемы.
Поэтому вы должны пометить его как финальный, когда вы неявно делаете класс финальным, делая его конструктор закрытым.
источник
Последний класс - это класс, который не может быть расширен. Также методы могут быть объявлены как final, чтобы указать, что не может быть переопределено подклассами.
Предотвращение подкласса класса может быть особенно полезным, если вы пишете API или библиотеки и хотите избежать расширения для изменения базового поведения.
источник
Одно из преимуществ сохранения класса как финального:
Класс String остается окончательным, чтобы никто не мог переопределить его методы и изменить функциональность. Например, никто не может изменить функциональность метода length (). Он всегда будет возвращать длину строки.
Разработчик этого класса не хотел, чтобы кто-то изменил функциональность этого класса, поэтому он сохранил его как окончательный.
источник
Да, иногда вы можете этого хотеть, либо по соображениям безопасности, либо по соображениям скорости. Это сделано также в C ++. Это не может быть , что применимо для программ, но в большей степени , за рамки. http://www.glenmccl.com/perfj_025.htm
источник
В Java окончательное ключевое слово используется для случаев ниже.
источник
Финальные занятия не могут быть продлены. Поэтому, если вы хотите, чтобы класс вел себя определенным образом, а кто-то не переопределял методы (возможно, с менее эффективным и более вредоносным кодом), вы можете объявить весь класс как финальные или особые методы, которыми вы не хотите быть. изменилось.
Поскольку объявление класса не препятствует созданию экземпляра класса, это не означает, что он не даст классу иметь характеристики объекта. Просто вам придется придерживаться методов так, как они объявлены в классе.
источник
думайте о ФИНАЛЕ как о «конце линии» - этот парень больше не может производить потомство. Поэтому, когда вы видите это таким образом, вы обнаружите множество реальных сценариев, которые требуют пометить маркер «конца строки» для класса. Это доменный дизайн - если ваш домен требует, чтобы данный ENTITY (класс) не мог создавать подклассы, пометьте его как FINAL.
Я должен отметить, что ничто не мешает вам наследовать класс «должен быть помечен как окончательный». Но это обычно классифицируется как «злоупотребление наследованием», и это делается потому, что чаще всего вы хотели бы унаследовать некоторую функцию от базового класса в вашем классе.
Лучший подход - взглянуть на предметную область и позволить ей диктовать свои дизайнерские решения.
источник
Как было сказано выше, если вы хотите, чтобы никто не мог изменить функциональность метода, вы можете объявить его как окончательный.
Пример: путь к файлу сервера приложений для загрузки / выгрузки, разбиение строки на основе смещения, такие методы вы можете объявить как Final, чтобы эти функции метода не были изменены. И если вам нужны такие конечные методы в отдельном классе, определите этот класс как класс Final. Таким образом, в классе Final будут все методы final, а метод Final может быть объявлен и определен в классе non-final.
источник
Класс Android Looper является хорошим практическим примером этого. http://developer.android.com/reference/android/os/Looper.html
Класс Looper предоставляет определенные функциональные возможности, которые НЕ предназначены для переопределения каким-либо другим классом. Следовательно, здесь нет подкласса.
источник
Допустим, у вас есть
Employee
класс, у которого есть методgreet
. Когдаgreet
метод вызывается, он просто печатаетHello everyone!
. Так что это ожидаемое поведение поgreet
методуТеперь позвольте
GrumpyEmployee
подклассуEmployee
и переопределитьgreet
метод, как показано ниже.Теперь в приведенном ниже коде посмотрите на
sayHello
метод. Он принимаетEmployee
экземпляр в качестве параметра и вызывает метод greet, надеясь, что он скажет,Hello everyone!
но то, что мы получаем, этоGet lost!
. Это изменение в поведении происходит из-заEmployee grumpyEmployee = new GrumpyEmployee();
Этой ситуации можно избежать, если
Employee
класс был сделанfinal
. Только представьте, сколько хаоса может вызвать дерзкий программист, еслиString
Class не объявлен какfinal
.источник
Финальный класс не может быть продлен дальше. Если нам не нужно делать класс наследуемым в Java, мы можем использовать этот подход.
Если нам просто нужно создать определенные методы в классе, чтобы они не были переопределены, мы просто можем поставить перед ними ключевое слово final. Там класс все еще наследуется.
источник
Ориентация объекта - это не наследование, а инкапсуляция. И наследование нарушает инкапсуляцию.
Объявление финала класса имеет смысл во многих случаях. Любой объект, представляющий «ценность», такую как цвет или сумма денег, может быть конечным. Они стоят сами по себе.
Если вы пишете библиотеки, сделайте ваши классы окончательными, если вы явно не сделаете отступ для их производных. В противном случае люди могут получить ваши классы и переопределить методы, нарушив ваши предположения / инварианты. Это также может иметь последствия для безопасности.
Джошуа Блох в «Эффективной Java» рекомендует явно разрабатывать наследование или запрещать его, и отмечает, что проектирование наследования не так просто.
источник