JavaRush /Blog Java /Random-VI /Vậy là cuối cùng...
Алексей
Mức độ

Vậy là cuối cùng...

Xuất bản trong nhóm
Có một từ khóa trong java - final. Nó có thể được áp dụng cho các lớp, phương thức, biến (bao gồm cả đối số phương thức). Vậy là cuối cùng... - 1Đối với một lớp, điều này có nghĩa là lớp đó không thể có các lớp con, tức là Việc thừa kế bị cấm. Điều này rất hữu ích khi tạo immutablecác đối tượng (không thay đổi), ví dụ như một lớp Stringđược khai báo là final.
public final class String{
}

class SubString extends String{ //Compilation error
}
Cũng cần lưu ý rằng công cụ sửa đổi không thể được áp dụng cho các lớp trừu tượng (với từ khóa abstract), finalbởi vì đây là những khái niệm loại trừ lẫn nhau. Đối với một phương thức finalcó nghĩa là nó không thể bị ghi đè trong các lớp con. Điều này hữu ích khi chúng ta muốn việc triển khai ban đầu không bị ghi đè.
public class SuperClass{
    public final void printReport(){
        System.out.println("Report");
    }
}

class SubClass extends SuperClass{
    public void printReport(){  //Compilation error
        System.out.println("MyReport");
    }
}
Đối với các biến kiểu nguyên thủy, điều này có nghĩa là một khi đã được gán, giá trị không thể thay đổi. Đối với các biến tham chiếu, điều này có nghĩa là khi một đối tượng được gán thì tham chiếu đến đối tượng đó không thể thay đổi. Nó quan trọng! Liên kết không thể thay đổi nhưng trạng thái của đối tượng có thể thay đổi. Với java 8, khái niệm này đã xuất hiện - effectively final. Nó chỉ áp dụng cho các biến (bao gồm cả đối số phương thức). Vấn đề là mặc dù rõ ràng là không có từ khóa final, nhưng giá trị của biến không thay đổi sau khi khởi tạo. Nói cách khác, bạn có thể thay thế một từ cho một biến như vậy finalmà không gặp lỗi biên dịch. effectively finalCác biến có thể được sử dụng bên trong các lớp cục bộ ( Local Inner Classes), lớp ẩn danh ( Anonymous Inner Classes), luồng (API luồng).
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
}
Bây giờ chúng ta hãy có một cuộc phỏng vấn nhỏ. Suy cho cùng, mục tiêu của việc tham gia khóa học JavaRush là trở thành nhà phát triển Java và có được một công việc thú vị và được trả lương cao. Vì vậy, hãy bắt đầu.
  1. Bạn có thể nói gì về một mảng khi nó được khai báo final?

  2. Được biết, lớp Stringimmutable, lớp được khai báo final, giá trị của chuỗi được lưu trữ trong một mảng char, được đánh dấu bằng từ khóa final.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
Có thể thay thế giá trị của một đối tượng String(mà không thay đổi tham chiếu đến đối tượng) không? Đây là những câu hỏi phỏng vấn thực tế. Và như thực tế cho thấy, nhiều người trả lời sai. Hiểu cách sử dụng từ khóa final, đặc biệt là đối với các biến tham chiếu, là rất quan trọng. Trong khi bạn đang suy nghĩ, hãy chuyển nhanh sang nhóm JavaRush. Vui lòng thêm một khối trong trình soạn thảo văn bản của bạn để cho phép bạn ẩn nội dung và khi bạn nhấp vào nó, hãy hiển thị nội dung này. Câu trả lời:
  1. Bởi vì mảng là một đối tượng, finalnghĩa là sau khi gán tham chiếu cho một đối tượng thì không thể thay đổi được nữa nhưng trạng thái của đối tượng có thể thay đổi được.

    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. Vâng, bạn có thể. Điều quan trọng là phải hiểu cách sử dụng từ có gai finalvới đồ vật. Sử dụng ReflectionAPI để thay thế giá trị.

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
         */
    }
}
Xin lưu ý rằng nếu chúng ta cố gắng thay đổi biến cuối cùng của kiểu nguyên thủy theo cách này thì sẽ không có gì hiệu quả. Tôi khuyên bạn nên thuyết phục bản thân về điều này: chẳng hạn, hãy tạo một lớp Java với final intmột trường và cố gắng thay đổi giá trị của nó thông qua API Reflection. Chúc mọi người may mắn!
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION