Existe uma palavra-chave em java -
final
. Pode ser aplicado a classes, métodos, variáveis (incluindo argumentos de métodos). Para uma classe, isso significa que a classe não pode ter subclasses, ou seja, A herança é proibida. Isso é útil ao criar immutable
objetos (imutáveis), por exemplo, uma classe String
declarada 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
), final
porque esses são conceitos mutuamente exclusivos. Pois um método final
significa 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 final
sem erro de compilação. effectively final
Variá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.
-
O que você pode dizer sobre um array quando ele é declarado
final
? -
Sabe-se que a classe
String
éimmutable
, a classe é declaradafinal
, o valor da string é armazenado em um arraychar
, que é marcado com a palavra-chavefinal
.
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:
-
Porque um array é um objeto, o que
final
significa 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
-
Sim você pode. A chave é entender o uso da palavra farpada
final
com 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 int
um campo e tente alterar seu valor através da API Reflection. Boa sorte a todos!
GO TO FULL VERSION