Я скомпилировал свои предыдущие статьи на Github, приветствую всех в звездахGitHub.com/Next Day Picks/Не голоден…Отправила эту статью
final
это ключевое слово в Java, а также очень важное ключевое слово в Java Final модифицированные классы, методы и переменные имеют разные значения;finally
Это также ключевое слово, но мы можем использовать finally в сочетании с другими ключевыми словами для выполнения некоторых операций композиции;finalize
это нежелательный метод, это предок объектаObject
Метод в , механизм finalize теперь устарел. В этой статье cxuan поможет вам начать с этих трех ключевых слов и поможет вам понять эти три ключевых слова простым способом с точки зрения использования, применения и принципа.
окончательный, наконец, и завершить
Я считаю, что все здесь — старшие программисты, поэтому нет необходимости говорить больше о базовом ключевом слове final. Тем не менее, мы все еще должны заботиться о читателях Xiaobai, ведь все мы пришли из Xiaobai.
final украшает классы, свойства и методы
final
Может использоваться для модификации классов, окончательные измененные классы не позволяют наследовать другие классы, то есть окончательные измененные классы уникальны. Следующее
Сначала мы определяем класс FinalUsage, который украшен final, и в то же время мы определяем класс FinalUsageExtend, который хочет继承(extend)
FinalUsage, после того, как мы наследуем как выше, компилятор не дает нам играть так, он подсказывает намНе могу получить от FinalUsageНаследование классов, почему? Не волнуйтесь, это соглашение Java, и есть несколько причин, по которым это не обязательно, просто следуйте ему.
final
Его можно использовать для изменения методов. Методы Final Modified не могут быть переопределены. Давайте сначала продемонстрируем ситуацию без изменения ключевого слова final.
Как показано выше, мы расширяем класс FinalUsage классом FinalUsageExtend и предоставляемwriteArticle
переопределение метода. С компиляцией таким образом проблем нет, ключевым моментом переписывания является@Override
Согласованность аннотаций и модификаторов методов, имен и возвращаемых значений.
Примечание. Многие программисты игнорируют @Override при переопределении методов, что, несомненно, усложнит чтение кода, что не рекомендуется.
Когда мы используем окончательный модифицированный метод, этот метод нельзя переопределить, как показано ниже.
Когда мы объявляем метод writeArticle недействительным, переопределенный метод сообщит об ошибке и не сможет переопределить метод writeArticle.
final
Переменные могут быть изменены, а окончательные измененные переменные не могут быть изменены после их определения, как показано ниже.
Ошибка, которую подсказывает компилятор, заключается в том, что вы не можете наследовать класс, украшенный final.
Мы используем строку String выше, и String по умолчанию является final.На самом деле, нет смысла использовать final модификацию, потому что строка не может быть перезаписана в первую очередь, что не объясняет проблему.
Давайте перепишем его, используя базовые типы данных, чтобы продемонстрировать
Также видно, что компилятор все же дает подсказку о том, что age нельзя перезаписать, поэтому можно доказать, что финальную измененную переменную нельзя переписать.
В Java есть не только базовые типы данных, но и ссылочные типы данных, так что же происходит, когда ссылочный тип финализируется? Давайте посмотрим на код ниже
Сначала постройтеPerson
своего рода
public class Person {
int id;
String name;
get() and set() ...
toString()...
}
Затем мы определяем последнюю переменную Person.
static final Person person = new Person(25,"cxuan");
public static void main(String[] args) {
System.out.println(person);
person.setId(26);
person.setName("cxuan001");
System.out.println(person);
}
Вывод, вы обнаружите странное явление, почему мы явно сменили id и имя лично, но компилятор не сообщил об ошибке?
Это связано с тем, что окончательный измененный ссылочный тип гарантирует только то, что ссылка на объект не изменится. Данные внутри объекта могут изменяться. Это предполагает размещение объектов в памяти, о чем мы поговорим позже.
наконец гарантирует, что программа должна быть выполнена
finally
Это механизм, гарантирующий, что программа должна быть выполнена. Это также ключевое слово в Java. Вообще говоря, finally обычно не используется сам по себе. Обычно он используется с блоками try. Например, ниже приведена попытка... наконец кодовый блок
try{
lock.lock();
}finally {
lock.unlock();
}
Это пример кода блокировки/разблокировки.После того, как блокировка заблокирована, операция разблокировки выполняется в finally.Поскольку finally может гарантировать, что код должен быть выполнен, некоторые более важные коды обычно помещаются в finally, например, операция разблокировки. , операции закрытия потока, операции освобождения соединения и т. д.
Также работает с lock.lock() при возникновении исключенияtry...catch...finally
использовать вместе
try{
lock.lock();
}catch(Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
try...finally Этот способ записи подходит для JDK1.7 до того, как в JDK1.7 была введена новая операция закрытого потока, то естьtry...with...resources
, в Java появился оператор try-with-resources, упрощающий try-catch-finally до try-catch, который на самом деле является синтаксическим сахаром, а не дополнительным синтаксисом. try...with...resources по-прежнему преобразуются в операторы try-catch-finally во время компиляции.
语法糖(Syntactic sugar)
, также переводится как «подслащенная грамматика», относится к определенной грамматике, добавленной к компьютерному языку.Эта грамматика не влияет на функции языка, но более удобна для использования программистами. Вообще говоря, использование синтаксического сахара может повысить читабельность программы, тем самым уменьшив вероятность ошибки в программном коде.
В Java есть несколько синтаксических сахаров для упрощения использования программистом, о которых мы поговорим позже, когда у нас будет возможность.
Роль доработки
finalize — класс-предокObject
Метод класса, предназначенный для обеспечения того, чтобы объект завершил освобождение определенного ресурса перед сборкой мусора. finalize теперь устарела и была явно помечена какdeprecated
.
Глубокое понимание final, final и finalize
окончательный дизайн
Многие языки программирования каким-то образом сообщают компилятору, что определенный фрагмент данных является константой. Иногда полезны постоянные данные, например
- Постоянная времени компиляции, которая никогда не меняется. Напримерstatic final int num = 1024
- значение, которое инициализируется во время выполнения, и вы не хотите его менять
окончательный дизайн будет иabstract
конфликты в дизайне, потому что ключевое слово abstract в первую очередь изменяет抽象类
, в то время как абстрактные классы должны быть реализованы конкретными классами. final означает, что наследование запрещено, и проблем с реализацией не будет. Потому что только после наследования подкласс может реализовать метод родительского класса.
все в классеprivate
неявно указаны какfinal
Да, нет никакого дополнительного смысла в использовании final в приватно оформленном коде.
пустой финал
Java разрешен空白 final
Пустой final указывает на объявление как final , но не присваивает ему значение для его инициализации. Но в любом случае компилятору нужно инициализировать final, поэтому задача этой инициализации передается构造器
для завершения пустой финал дает больше гибкости для финала. Следующий код
public class FinalTest {
final Integer finalNum;
public FinalTest(){
finalNum = 11;
}
public FinalTest(int num){
finalNum = num;
}
public static void main(String[] args) {
new FinalTest();
new FinalTest(25);
}
}
Инициализируйте разные финалы в разных конструкторах, чтобы сделать использование finalNum более гибким.
Существует два основных способа использования final:不可变
и效率
- Immutable: Immutable означает блокировку метода (обратите внимание, что он не заблокирован), и основное внимание уделяется предотвращению перезаписи других методов.
- Эффективность: Это в основном для ранней версии Java.В ранней реализации Java, если метод объявлен final, это означает, что компилятор изменит вызов этого метода на
内嵌调用
, но не принесли существенной оптимизации производительности. Этот вид вызова довольно безвкусен.В Java5/6 виртуальная машина точки доступа автоматически обнаруживает встроенные вызовы и оптимизирует их, поэтому есть один основной способ использования окончательной модификации: неизменяемый.
Примечание: final не является Immutable, Immutable действительно неизменяем.
финал не соответствует действительностиImmutable
, потому что объект, на который ссылается ключевое слово final, может быть изменен. Если мы действительно хотим, чтобы объект был неизменным, нам обычно нужен соответствующий класс для поддержки неизменного поведения, например следующий код
final List<String> fList = new ArrayList();
fList.add("Hello");
fList.add("World");
List unmodfiableList = List.of("hello","world");
unmodfiableList.add("again");
List.of
Метод создает неизменяемый список. Immutable Immutable — хороший выбор во многих случаях, в целом при реализации Immutable необходимо обратить внимание на следующие моменты.
- Объявите класс как final, чтобы другие классы не расширялись.
- Объявляйте переменные-члены внутри класса (включая переменные экземпляра и переменные класса) как
private
илиfinal
Да, не предоставляйте методы, которые могут изменять переменные-члены, то есть методы установки. - При создании объекта вы обычно используете
deep-clone
, что помогает предотвратить изменение входного объекта другими пользователями при непосредственном назначении объекта. - настаивать
copy-on-write
В принципе, создайте приватную копию.
Улучшает ли final производительность?
Вопрос о том, может ли final повысить производительность, всегда был предметом споров в отрасли. Во многих книгах упоминается, что производительность можно повысить в определенных сценариях. Например, final можно использовать для поддержки встроенных методов JVM, которые могут быть изменены компилятором. Возможность компилировать и т.д., но многие из этих выводов основаны на предположениях.
Может быть, ответ R даст нам некоторые выводыУуху. Call.com/question/21…
грубо говоряНезависимо от того, объявлена ли локальная переменная с модификацией ключевого слова final или без нее, эффективность доступа к ней одинакова..
Например, следующий код (версия без final)
static int foo() {
int a = someValueA();
int b = someValueB();
return a + b; // 这里访问局部变量
}
версия с финалом
static int foo() {
final int a = someValueA();
final int b = someValueB();
return a + b; // 这里访问局部变量
}
использоватьjavac
Результат после компиляции точно такой же.
invokestatic someValueA:()I
istore_0 // 设置a的值
invokestatic someValueB:()I
istore_1 // 设置b的值
iload_0 // 读取a的值
iload_1 // 读取b的值
iadd
ireturn
Поскольку выше используется ссылочный тип, байт-код тот же.
Если это постоянный тип, давайте посмотрим
// 带 final
static int foo(){
final int a = 11;
final int b = 12;
return a + b;
}
// 不带 final
static int foo(){
int a = 11;
int b = 12;
return a + b;
}
Давайте скомпилируем два отдельноfoo
метод, вы найдете следующий байт-код
Слева код, модифицированный ключевым словом non-final, а справа код, измененный ключевым словом final Сравнивая два байт-кода, можно сделать следующие выводы.
- Int a = 11 или int a = 12 обрабатываются как константы с модификаторами final или без них.
- При возврате a + b без final будет рассматриваться как переменная; a + b с модификацией final будет рассматриваться как константа напрямую.
На самом деле, этот уровень различий оказывает большее влияние только на более простую JVM, потому что такая VM в значительной степени зависит от интерпретатора, а байт-код в исходном файле класса выполняется как есть; для высокопроизводительной JVM (например, HotSpot, J9 и т. д.) не действуют.
Таким образом, большую часть влияния final на оптимизацию производительности можно игнорировать напрямую, мы используем final больше из-за его неизменности.
Глубокое понимание наконец
Мы говорили об использовании finally выше, и его роль заключается в том, чтобы гарантировать, что после выполнения кода в блоке try будет выполнено выражение в finally. Независимо от того, выбрасывается ли исключение в блоке try.
Итак, давайте подробнее рассмотрим finally, что такое байт-код finally и природу выполнения finally.
- Прежде всего, мы знаем, что блок finally будет выполняться только тогда, когда выполняется блок try, и finally не будет существовать сам по себе..
Это не требует дополнительных пояснений, это правило известно всем. finally должен использоваться с блоком try или блоком try catch.
- Во-вторых, блок finally выполняется перед оператором передачи управления после выхода из блока try или когда блок try не завершен, но следует оператор передачи управления (return/continue/break).
Это на самом деле объясняет время выполнения finally Давайте возьмем return в качестве примера, чтобы увидеть, так ли это.
Следующий код
static int mayThrowException(){
try{
return 1;
}finally {
System.out.println("finally");
}
}
public static void main(String[] args) {
System.out.println(FinallyTest.mayThrowException());
}
По результату выполнения можно доказать, что finally выполняется перед возвратом.
Когда наконец будет возвращено значение, он вернется напрямую. Больше никаких возвращаемых значений из try или catch.
static int mayThrowException(){
try{
return 1;
}finally {
return 2;
}
}
public static void main(String[] args) {
System.out.println(FinallyTest.mayThrowException());
}
- Оператор передачи управления сохраняет возвращаемое значение в локальной переменной перед выполнением оператора finally.
Посмотрите на код ниже
static int mayThrowException(){
int i = 100;
try {
return i;
}finally {
++i;
}
}
public static void main(String[] args) {
System.out.println(FinallyTest.mayThrowException());
}
Приведенный выше код может показать, что return i выполняется до ++i, а return i временно сохраняет значение i и возвращается с finally.
Суть, наконец,
Давайте посмотрим на кусок кода
public static void main(String[] args) {
int a1 = 0;
try {
a1 = 1;
}catch (Exception e){
a1 = 2;
}finally {
a1 = 3;
}
System.out.println(a1);
}
Каков результат этого кода? Ответ 3, почему?
Сомневаетесь, давайте сначала посмотрим на байткод этого кода
Я для вас отметил китайские комментарии байткода, тут нужно обратить внимание на следующееException table
, Таблица исключений — это таблица исключений, каждая запись в таблице исключений представляет собой генератор исключений, а генератор исключений состоит из указателя From, указателя To, указателя Target и типа исключения, которое должно быть перехвачено.
Таким образом, для приведенного выше кода есть три пути выполнения.
- Если в блоке операторов try возникает исключение, относящееся к exception и его подклассам, переходите к обработке catch.
- Если в блоке оператора try возникает исключение, не принадлежащее к исключению и его подклассам, перейдите к окончательной обработке.
- Если в блоке catch возникает новое исключение, перейдите к окончательной обработке
До сих пор мы не говорили, в чем суть finally, если вы внимательно посмотрите на приведенный выше байт-код, вы обнаружите, что finally на самом деле поместитa1 = 3
байт-кодiconst_3 и istore_1Поместите его после блока try и блока catch, чтобы приведенный выше код был эквивалентен
public static void main(String[] args) {
int a1 = 0;
try {
a1 = 1;
// finally a1 = 3
}catch (Exception e){
a1 = 2;
// finally a1 = 3
}finally {
a1 = 3;
}
System.out.println(a1);
}
Таблица исключений выше толькоThrowable
подклассисключение и ошибкаБудет выполнена таблица исключений для обхода исключений. В нормальных условиях без блока try не существует таблицы исключений. Давайте проверим это.
public static void main(String[] args) {
int a1 = 1;
System.out.println(a1);
}
Например, мы использовали очень простую программу выше для проверки, и после компиляции давайте посмотрим на ее байт-код
Как видите, таблицы исключений действительно нет.
наконец, он будет выполнен?
То, что мы обсуждали выше, — это случаи, когда finally обязательно будет выполнено, значит, наконец будет выполнено? Я не боюсь.
В дополнение к сбою питания компьютерного зала, взрыву компьютерного зала, попаданию воды в компьютерный зал, поражению компьютерного зала молнией, принудительному выключению и отключению источника питания, есть несколько ситуаций, которые могут окончательно не выполнять.
-
перечислить
System.exit
метод -
перечислить
Runtime.getRuntime().halt(exitStatus)
метод -
Сбой JVM (забавное лицо)
-
Если JVM достигает бесконечного цикла (или другого непрерывного, не завершающего оператора) в блоке try или catch
-
Уничтожила ли операционная система процесс JVM принудительно; например, kill -9 pid в UNIX.
-
не будет выполняться в случае сбоя хост-системы, такого как сбой питания, аппаратная ошибка, сбой ОС и т. д.
-
Если блок finally выполняется потоком демона, то все потоки, не являющиеся демонами, завершаются до вызова finally.
Finalize действительно бесполезен?
Мы кратко представили метод finalize выше и объяснили, что это плохая практика. Итак, каковы сроки завершения вызова? Почему финализация бесполезна?
Мы знаем, что существенная разница между Java и C++ заключается в том, что Java может自动管理内存
, в Java из-за автоматического механизма сбора GC нет гарантииfinalize
Методы будут выполнены своевременно (время сборки мусора неизвестно), и нет никакой гарантии, что они будут выполнены.
Другими словами, период выполнения finalize неизвестен, и мы не можем полагаться на метод finalize, чтобы помочь нам выполнить сборку мусора.Может случиться так, что сборщик мусора не сработает до того, как мы исчерпаем ресурсы, поэтому рекомендуется использовать метод finalize. отображение, когда ресурсы исчерпаны.Способ освобождения, например метод закрытия. В дополнение к этому, метод finalize также проглатывает исключения.
Финализация работает следующим образом: как только сборщик мусора готов освободить место, занимаемое объектом, он сначала вызываетfinalize
метод, и память, занимаемая объектом, не будет освобождена, пока не произойдет следующее действие по сборке мусора.Сборка мусора касается только памяти.
Мы не поддерживаем использование методов finalize в повседневной разработке.
Здравствуйте, я cxuan, техник. Всего я написал шесть PDF-файлов
«Краткое описание технологии Java Core» «Сводка ядра HTTP» «Базовые знания, которые должен знать программист» «Сводка ядра операционной системы» «Ядро ядра 2.0» Резюме вопросов для собеседования по Java
Теперь я предоставил вам ссылку на Baidu, вы можете щелкнуть ссылку ниже, чтобы получить ее.
Ссылка на сайт:disk.baidu.com/is/1my AES9Hi…Пароль: p9rs