Рубрики

финал, финал и финализация в Java

Это важный вопрос, касающийся точки зрения интервью.

последнее ключевое слово

final (нижний регистр) — зарезервированное ключевое слово в Java. Мы не можем использовать его как идентификатор, поскольку он зарезервирован. Мы можем использовать это ключевое слово с переменными, методами, а также с классами. Последнее ключевое слово в Java имеет различное значение в зависимости от того, применяется ли оно к переменной, классу или методу.

  1. final с переменными: значение переменной не может быть изменено после инициализации.

    class A {

        public static void main(String[] args)

        {

            // Не финальная переменная

            int a = 5;

      

            // финальная переменная

            final int b = 6;

      

            // изменение не финальной переменной: разрешено

            a++;

      

            // модифицируем конечную переменную:

            // Немедленно выдает ошибку времени компиляции.

            b++;

        }

    }

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

  2. final with Class: класс не может быть разделен на подклассы. Всякий раз, когда мы объявляем какой-либо класс как окончательный, это означает, что мы не можем расширить этот класс, или этот класс не может быть расширен или мы не можем создать подкласс этого класса.

    final class RR {

        public static void main(String[] args)

        {

            int a = 10;

        }

    }
    // здесь получаем ошибку времени компиляции,
    // мы не можем расширять RR, поскольку он является окончательным.

    class KK extends RR {

        // здесь больше кода с методом main

    }

  3. final with Method: метод не может быть переопределен подклассом. Всякий раз, когда мы объявляем какой-либо метод как финальный, это означает, что мы не можем переопределить этот метод.

    class QQ {

        final void rr() {}

        public static void main(String[] args)

        {

        }

    }

      

    class MM extends QQ {

      

        // Здесь мы получаем ошибку времени компиляции

        // так как не может расширять rr, поскольку оно является окончательным.

        void rr() {}

    }

    Примечание. Если класс объявлен как финальный, то по умолчанию все методы, присутствующие в этом классе, автоматически становятся финальными, а переменные — нет .

    // Java-программа для иллюстрации финального ключевого слова

    final class G {

      

        // по умолчанию это окончательно.

        void h() {}

      

        // по умолчанию это не окончательно.

        static int j = 30;

      

    public static void main(String[] args)

        {

            // Просмотреть измененное содержимое переменной j.

            j = 36;

            System.out.println(j);

        }

    }

    Выход :

    36

наконец ключевое слово

Так же как final является зарезервированным ключевым словом, так же, как и finally, также является зарезервированным ключевым словом в Java, то есть мы не можем использовать его в качестве идентификатора. Ключевое слово finally используется в сочетании с блоком try / catch и гарантирует выполнение части кода, даже если выдается исключение. Блок finally будет выполнен после блоков try и catch, но до того, как управление вернется в исходное состояние.

// Java-программа для окончательной демонстрации.

class Geek {

    // Метод, который выбрасывает исключение и имеет finally.

    // Этот метод будет вызываться внутри try-catch.

    static void A()

    {

        try {

            System.out.println("inside A");

            throw new RuntimeException("demo");

        }

        finally

        {

            System.out.println("A's finally");

        }

    }

  

    // Этот метод также вызывает finally. Этот метод

    // будет вызван снаружи try-catch.

    static void B()

    {

        try {

            System.out.println("inside B");

            return;

        }

        finally

        {

            System.out.println("B's finally");

        }

    }

  

    public static void main(String args[])

    {

        try {

            A();

        }

        catch (Exception e) {

            System.out.println("Exception caught");

        }

        B();

    }

}

Выход:

inside A
A's finally
Exception caught
inside B
B's finally

Существуют различные случаи, когда, наконец, можно использовать. Там обсуждаются ниже:

  1. Случай 1: исключения не происходят в программе

    // Java-программа для окончательной иллюстрации в
    // Случай, когда исключения не
    // происходит в программе

    class B {

        public static void main(String[] args)

        {

            int k = 55;

            try {

                System.out.println("In try block");

                int z = k / 55;

            }

      

            catch (ArithmeticException e) {

                System.out.println("In catch block");

                System.out.println("Dividing by zero but caught");

            }

      

            finally

            {

                System.out.println("Executes whether exception occurs or not");

            }

        }

    }

    Выход :

    In try block  
    Executes whether exception occurs or not

    Здесь выше исключение не происходит, но все же блок finally выполняется, так как finally предназначено для выполнения независимо от того, происходит исключение или нет.
    Поток вышеуказанной программы : сначала он запускается из основного метода, а затем переходит к блоку try и в try, поскольку исключение не происходит, поэтому поток не переходит к блоку перехвата, следовательно, поток переходит непосредственно от блока try к finally.

  2. Случай 2: Возникает исключительная ситуация и соответствующие совпадения блоков catch

    // Java-программа для окончательной иллюстрации в
    // Случай, когда возникают исключения
    // и совпадение в программе

    class C {

        public static void main(String[] args)

        {

            int k = 66;

            try {

                System.out.println("In try block");

                int z = k / 0;

                // Тщательно видеть поток не приходят сюда

                System.out.println("Flow dosen't came here");

            }

      

            catch (ArithmeticException e) {

                System.out.println("In catch block");

                System.out.println("Dividing by zero but caught");

            }

      

            finally

            {

                System.out.println("Executes whether an exception occurs or not");

            }

        }

    }

    Выход :

    In try block
    In catch block                         
    Dividing by zero but caught 
    Executes whether an exception occurs or not

    Здесь, вышеупомянутое исключение происходит, и соответствующий блок catch обнаружен, но все же блок finally выполняется, так как finally предназначено для выполнения, происходит ли исключение или нет, или найден соответствующий блок catch или нет.
    Поток вышеуказанной программы : сначала запускается из основного метода, а затем переходит к блоку try, и при попытке возникает арифметическое исключение, и соответствующий блок catch также доступен, поэтому поток переходит к блоку catch. После этого поток не проходит , чтобы попытаться заблокировать снова , так как только возникает исключение в блоке Ьги затем поток dosen't вернуться снова попробовать блок. После этого, наконец, execute, так как finally предназначено для выполнения независимо от того, происходит исключение или нет, или найден соответствующий блок перехвата или нет.

  3. Случай 3: возникает исключение, и соответствующий блок перехвата не найден / не соответствует

    // Java-программа для окончательной иллюстрации в
    // Случай, когда возникают исключения
    // и не совпадают ни с одним регистром в программе

    class D {

        public static void main(String[] args)

        {

            int k = 15;

            try {

                System.out.println("In try block");

                int z = k / 0;

            }

      

            catch (NullPointerException e) {

                System.out.println("In catch block");

                System.out.println("Dividing by zero but caught");

            }

      

            finally

            {

                System.out.println("Executes whether an exception occurs or not");

            }

        }

    }

    Выход :

    In try block  
    Executes whether an exception occurs or not
    Exception in thread "main":java.lang.ArithmeticException:
    / by zero followed by stack trace.

    Здесь выше исключение происходит, и соответствующий блок catch не найден / не совпадает, но все же, наконец, блок выполняется, так как finally предназначено для выполнения независимо от того, происходит исключение или нет, или соответствующий блок обнаружения найден / совпадает или нет.
    Поток Above программы: Первый начинается от основного метода , а затем идет попробовать блок и попробовать арифметическое происходит исключение и соответствующий блок улова не доступно , так течь dosen't идет поймать блок. После этого поток не проходит , чтобы попытаться заблокировать снова , так как только возникает исключение в блоке Ьги затем поток dosen't вернуться снова попробовать блок. После этого, наконец, execute, так как finally предназначено для выполнения независимо от того, происходит исключение или нет, или найден / совпадает соответствующий блок перехвата.

Применение блока finally . Таким образом, использование блока finally заключается в освобождении ресурсов . Означает, что все ресурсы, такие как сетевые подключения, соединения с базой данных, которые мы открыли в блоке try, необходимо закрыть, чтобы мы не потеряли наши ресурсы при открытии. Таким образом, эти ресурсы необходимо закрыть в блоке finally.

// Java-программа для иллюстрации
// использование блока finally

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintWriter;

  

class K {

private static final int SIZE = 10;

    public static void main(String[] args)

    {

  

        PrintWriter out = null;

        try {

            System.out.println("Entered try statement");

  

            // PrintWriter, FileWriter

            // классы в пакете io

            out = new PrintWriter(new FileWriter("OutFile.txt"));

        }

        catch (IOException e) {

            // Поскольку FileWriter в

            // блок try может выдать IOException

        }

  

        // Следующий блок наконец очищается

        // и затем закрывает PrintWriter.

  

        finally

        {

            if (out != null) {

                System.out.println("Closing PrintWriter");

                out.close();

            } else {

                System.out.println("PrintWriter not open");

            }

        }

    }

}

Выход :

Entered try statement
PrintWriter not open

Примечание . Блок finally является ключевым инструментом для предотвращения утечек ресурсов. Закрывая файл или восстанавливая ресурсы другим способом, поместите код в блок finally, чтобы ресурс всегда был восстановлен.

Как jdk 1.7 делает использование блока finally необязательным?

До тех пор, пока блок jdk 1.6, наконец, не станет похожим на героя, т.е. рекомендуется использовать его для освобождения ресурсов, но, начиная с версии 1.7, наконец, блок теперь является необязательным (однако вы можете использовать его). Поскольку ресурсы, которые мы открыли в блоке try, автоматически освобождаются / закрываются, когда поток программы достигает конца блока try.
Эта концепция автоматического освобождения ресурсов без использования блока finally называется оператором try-with-resources .

завершить метод

Это метод, который сборщик мусора всегда вызывает непосредственно перед удалением / уничтожением объекта, который подходит для сбора мусора, чтобы выполнить очистку . Операция очистки означает закрытие ресурсов, связанных с этим объектом, таких как соединение с базой данных, сетевое соединение или, можно сказать, перераспределение ресурсов. Помните, что это не зарезервированное ключевое слово.
Как только метод finalize завершается немедленно, сборщик мусора уничтожает этот объект. Метод finalize присутствует в классе Object и имеет следующий синтаксис:

protected void finalize throws Throwable{}

Так как класс Object содержит метод finalize, следовательно, метод finalize доступен для каждого java-класса, поскольку Object является суперклассом всех java-классов. Так как он доступен для каждого Java-класса, следовательно, Garbage Collector может вызывать метод finalize для любого Java-объекта.
Теперь метод finalize, который присутствует в классе Object, имеет пустую реализацию, в нашем классе есть действия по очистке, тогда мы должны переопределить этот метод, чтобы определить наши собственные действия по очистке.

Случаи, связанные с завершением метода:

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

    class Hello {

        public static void main(String[] args)

        {

            String s = new String("RR");

            s = null;

      

            // Запрос JVM для вызова метода сборщика мусора

            System.gc();

            System.out.println("Main Completes");

        }

      

        // Здесь переопределяем метод финализации

        public void finalize()

        {

            System.out.println("finalize method overriden");

        }

    }

    Выход :

    Main Completes

    Примечание : здесь выше вывод пришел только Main Completes, а не «завершение переопределения метода», потому что сборщик мусора вызывает метод finalize для того объекта класса, который подходит для сборки мусора. Здесь выше мы сделали->
    s = null и 's' является объектом класса String, поэтому будет вызываться метод finalize класса String, а не наш класс (т. е. класс Hello). Таким образом, мы модифицируем наш код как->

    Hello s = new Hello();
    s = null;
    

    Теперь вызывается наш класс, т. Е. Hello, метод финализации класса. Выход :

    finalize method overriden
    Main Completes

    Таким образом, Garbage Collector вызывает метод finalize для того объекта класса, который подходит для сборки мусора. Так что если объект String подходит для сборки мусора, то будет вызываться метод finalize класса String, а не метод финализации класса Hello .

  2. Случай 2: мы можем вызвать метод finalize явным образом, тогда он будет выполнен так же, как и обычный вызов метода, но объект не будет удален / уничтожен

    class Bye {

        public static void main(String[] args)

        {

            Bye m = new Bye();

      

            // Вызов метода finalize явно.

            m.finalize();

            m.finalize();

            m = null;

      

            // Запрос JVM для вызова метода сборщика мусора

            System.gc();

            System.out.println("Main Completes");

        }

      

        // Здесь переопределяем метод финализации

        public void finalize()

        {

            System.out.println("finalize method overriden");

        }

    }

    Выход :

    finalize method overriden 
    //call by programmer but object won't gets destroyed.
    finalize method overriden 
    //call by programmer but object won't gets destroyed.
    Main Completes
    finalize method overriden 
    //call by Garbage Collector just before destroying the object.
    

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

  3. Случай 3:
    • Часть а) Если программист вызывает метод finalize, при выполнении метода finalize возникает неконтролируемое исключение.

      class Hi {

          public static void main(String[] args)

          {

              Hi j = new Hi();

        

              // Вызов метода finalize явно.

              j.finalize();

        

              j = null;

        

              // Запрос JVM для вызова метода сборщика мусора

              System.gc();

              System.out.println("Main Completes");

          }

        

          // Здесь переопределяем метод финализации

          public void finalize()

          {

              System.out.println("finalize method overriden");

              System.out.println(10 / 0);

          }

      }

      Выход :

      exception in thread "main" java.lang.ArithmeticException:
      / by zero followed by stack trace.

      Итак, ключевой момент заключается в следующем: если программист вызывает метод finalize, при выполнении метода finalize возникает неконтролируемое исключение, то JVM ненормально завершает программу из-за возрастающего исключения. Таким образом, в этом случае завершение программы является ненормальным .

    • часть б) Если сборщик мусора вызывает метод finalize, то при выполнении метода finalize возникает неконтролируемое исключение.

      class RR {

          public static void main(String[] args)

          {

              RR q = new RR();

              q = null;

        

              // Запрос JVM для вызова метода сборщика мусора

              System.gc();

              System.out.println("Main Completes");

          }

        

          // Здесь переопределяем метод финализации

          public void finalize()

          {

              System.out.println("finalize method overriden");

              System.out.println(10 / 0);

          }

      }

      Выход :

      finalize method overriden
      Main Completes
      

      Итак, ключевой момент таков: если сборщик мусора вызывает метод finalize, а при выполнении метода finalize возникает неконтролируемое исключение, то JVM игнорирует это исключение, и остальная часть программы будет продолжена в обычном режиме. Таким образом, в этом случае завершение программы нормальное и не ненормальное.

Важные моменты: