У java є ключове слово –
Для класу це означає, що клас не зможе мати підкласів, тобто заборонено успадкування. Це корисно при створенні
final. Воно може застосовуватися до класів, методів, змінних (в тому числі аргументів методів).
Для класу це означає, що клас не зможе мати підкласів, тобто заборонено успадкування. Це корисно при створенні immutable (незмінюваних) об'єктів, наприклад, клас String оголошений як final.
public final class String{
}
class SubString extends String{ //Помилка компіляції
}
Слід також зазначити, що до абстрактних класів (з ключовим словом abstract), не можна застосувати модифікатор final, тому що це взаємовиключні поняття.
Для методу final означає, що він не може бути перевизначений у підкласах. Це корисно, коли ми хочемо, щоб початкову реалізацію не можна було перевизначити.
public class SuperClass{
public final void printReport(){
System.out.println("Report");
}
}
class SubClass extends SuperClass{
public void printReport(){ //Помилка компіляції
System.out.println("MyReport");
}
}
Для змінних примітивного типу це означає, що одного разу присвоєне значення не може бути змінене.
Для посилальних змінних це означає, що після присвоєння об'єкта, не можна змінити посилання на даний об'єкт. Це важливо! Посилання змінити не можна, але стан об'єкта змінювати можна.
З java 8 з'явилося поняття — effectively final. Застосовується воно тільки до змінних (в тому числі аргументів методів). Суть у тому, що незважаючи на явну відсутність ключового слова final, значення змінної не змінюється після ініціалізації. Іншими словами, до такої змінної можна підставити слово final без помилки компіляції. effectively final змінні можуть бути використані всередині локальних класів (Local Inner Classes), анонімних класів (Anonymous Inner Classes), стрімах (Stream API).
public void someMethod(){
// У прикладі нижче і a і b - effectively final, тому що значення встановлюються одного разу:
int a = 1;
int b;
if (a == 2) b = 3;
else b = 4;
// с НЕ є effectively final, тому що значення змінюється
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)); //Помилка компіляції
}
А тепер давайте влаштуємо невелике співбесіду. Адже основна мета проходження курсу JavaRush – стати Java розробником та влаштуватися на цікаву і добре оплачувану роботу.
І так, почнемо.
Що можна сказати про масив, коли він оголошений
final?Відомо, що клас
String—immutable, клас оголошенийfinal, значення рядка зберігається у масивіchar, який позначений ключовим словомfinal.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
Чи можна підмінити значення у об'єкта String (не змінюючи посилання на об'єкт)?
Це реальні питання зі співбесіди. І як показує практика, багато хто відповідає на них невірно. Розуміння використання ключового слова final, особливо для посилальних змінних – дуже важливо.
Поки ви розмірковуєте, невеликий відступ до команди JavaRush. Прохання додати у текстовому редакторі якийсь блок, що дозволяє приховувати вміст, а при натисканні по ньому – показувати цей вміст.
Відповіді:
Тому що масив – це об'єкт, то
finalозначає, що після присвоєння посилання на об'єкт, вже не можна її змінити, але можна змінювати стан об'єкта.final int[] array = {1,2,3,4,5}; array[0] = 9; //ок, тому що змінюємо вміст масиву – {9,2,3,4,5} array = new int[5]; //помилка компіляціїТак, можна. Ключовий момент – це розуміння використання колючого слова
finalз об'єктами. Для підміни значення використовує ReflectionAPI.
import java.lang.reflect.Field;
class B {
public static void main(String[] args) throws Exception {
String value = "Old value";
System.out.println(value);
//Отримуємо поле value у класі String
Field field = value.getClass().getDeclaredField("value");
//Дозволяємо змінювати його
field.setAccessible(true);
//Встановлюємо нове значення
field.set(value, "JavaRush".toCharArray());
System.out.println(value);
/* Вивід:
* Old value
* JavaRush
*/
}
}
Зверніть увагу, що якби ми спробували змінити таким чином фінальну змінну примітивного типу, то нічого б не вийшло. Пропоную вам самостійно в цьому впевнитися: створити Java клас, наприклад, з final int полем і спробувати змінити його значення через Reflection API.
Всім удачі!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ