JavaRush /Blogue Java /Random-PT /Então final...
Алексей
Nível 32

Então final...

Publicado no grupo Random-PT
Existe uma palavra-chave em java - final. Pode ser aplicado a classes, métodos, variáveis ​​(incluindo argumentos de métodos). Então, final... - 1Para uma classe, isso significa que a classe não pode ter subclasses, ou seja, A herança é proibida. Isso é útil ao criar immutableobjetos (imutáveis), por exemplo, uma classe Stringdeclarada como final.
public final class String{
}

class SubString extends String{ //Compilation error
}
Deve-se notar também que o modificador não pode ser aplicado a classes abstratas (com a palavra-chave abstract), finalporque esses são conceitos mutuamente exclusivos. Pois um método finalsignifica que ele não pode ser substituído em subclasses. Isto é útil quando queremos que a implementação original não seja substituída.
public class SuperClass{
    public final void printReport(){
        System.out.println("Report");
    }
}

class SubClass extends SuperClass{
    public void printReport(){  //Compilation error
        System.out.println("MyReport");
    }
}
Para variáveis ​​de tipo primitivo, isso significa que, uma vez atribuído, o valor não pode ser alterado. Para variáveis ​​de referência, isso significa que, uma vez atribuído um objeto, a referência a esse objeto não pode ser alterada. É importante! O link não pode ser alterado, mas o estado do objeto pode ser alterado. Com o java 8 apareceu o conceito - effectively final. Aplica-se apenas a variáveis ​​(incluindo argumentos de método). A questão é que, apesar da óbvia ausência da palavra-chave final, o valor da variável não muda após a inicialização. Em outras palavras, você pode substituir tal variável por uma palavra finalsem erro de compilação. effectively finalVariáveis ​​podem ser usadas dentro de classes locais ( Local Inner Classes), classes anônimas ( Anonymous Inner Classes), streams (API Stream).
public void someMethod(){
    // In the example below, both a and b are effectively final, since the values ​​are set once:
    int a = 1;
    int b;
    if (a == 2) b = 3;
    else b = 4;
    // c is NOT effectively final because value changes
    int c = 10;
    c++;

    Stream.of(1, 2).forEach(s-> System.out.println(s + a)); //Ок
    Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Compilation error
}
Agora vamos fazer uma pequena entrevista. Afinal, o objetivo de fazer o curso JavaRush é se tornar um desenvolvedor Java e conseguir um emprego interessante e bem remunerado. Então, vamos começar.
  1. O que você pode dizer sobre um array quando ele é declarado final?

  2. Sabe-se que a classe Stringé immutable, a classe é declarada final, o valor da string é armazenado em um array char, que é marcado com a palavra-chave final.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
É possível substituir o valor de um objeto String(sem alterar a referência ao objeto)? Estas são perguntas reais da entrevista. E como mostra a prática, muitos respondem incorretamente. Compreender o uso da palavra-chave final, especialmente para variáveis ​​de referência, é muito importante. Enquanto você pensa, uma rápida digressão para a equipe JavaRush. Adicione um bloco em seu editor de texto que permita ocultar o conteúdo e, ao clicar nele, mostre esse conteúdo. Respostas:
  1. Porque um array é um objeto, o que finalsignifica que após atribuir uma referência a um objeto, ele não pode mais ser alterado, mas o estado do objeto pode ser alterado.

    final int[] array = {1,2,3,4,5};
    array[0] = 9;	//ok, because change the contents of the array - {9,2,3,4,5}
    array = new int[5]; //compile error
  2. Sim você pode. A chave é entender o uso da palavra farpada finalcom objetos. Usa ReflectionAPI para substituir o valor.

import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        //Get the value field in the String class
        Field field = value.getClass().getDeclaredField("value");
        //Let's change it
        field.setAccessible(true);
        //Set new value
        field.set(value, "JavaRush".toCharArray());

        System.out.println(value);

        /* Вывод:
         * Old value
         * JavaRush
         */
    }
}
Observe que se tentássemos alterar a variável final de um tipo primitivo dessa maneira, nada funcionaria. Sugiro que você se convença disso: crie uma classe Java, por exemplo, com final intum campo e tente alterar seu valor através da API Reflection. Boa sorte a todos!
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION