2012-04-26 38 views
46

Mã sau trong Java sử dụng mảng final của String và không có câu hỏi nào về nó.mảng cuối cùng trong Java

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

Nó hiển thị kết quả sau trên bảng điều khiển.

I can never change 

Các mã sau cũng đi mà không bất kỳ câu hỏi.

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    //CONSTANT_ARRAY={"I", "can", "never", "change"}; //Error - can not assign to final variable CONSTANT_ARRAY. 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

Rõ ràng, dòng nhận xét gây ra lỗi cụ thể bởi vì chúng tôi đang cố gắng để phân công lại các tuyên bố final mảng kiểu String.


Còn mã sau đây.

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    CONSTANT_ARRAY[2] = "always"; //Compiles fine. 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

và nó sẽ hiển thị I can always change có nghĩa là chúng ta có thể quản lý để sửa đổi giá trị của final mảng kiểu String. Chúng ta có thể sửa đổi toàn bộ mảng theo cách này mà không vi phạm quy tắc của final không?

Trả lời

75

final trong Java ảnh hưởng đến biến số , không có gì liên quan đến đối tượng bạn đang gán cho nó.

final String[] myArray = { "hi", "there" }; 
myArray = anotherArray; // Error, you can't do that. myArray is final 
myArray[0] = "over"; // perfectly fine, final has nothing to do with it 

Chỉnh sửa để thêm từ nhận xét: Lưu ý rằng tôi đã nói đối tượng bạn đang gán cho nó. Trong Java một mảng là một đối tượng. Điều này cũng áp dụng cho bất kỳ đối tượng nào khác:

final List<String> myList = new ArrayList<String>(): 
myList = anotherList; // error, you can't do that 
myList.add("Hi there!"); // perfectly fine. 
+3

Bạn nói _object_, và đó là tốt này áp dụng cho mọi đối tượng, không chỉ là mảng Đó là tốt để sửa đổi đối tượng mà là.. Ví dụ, 'cuối cùng Danh sách danh sách = new ArrayList (); list.add (" foo ");'. –

9

Bạn chỉ có thể thực hiện để tham chiếu mảng không thể thay đổi. Nếu bạn muốn các thành phần không thể thay đổi được, bạn cần sử dụng một bộ sưu tập không thể sửa đổi được.

3

Khi bạn khai báo mảng cuối cùng, bạn có thể thay đổi các phần tử trong mảng, tuy nhiên bạn không thể thay đổi tham chiếu của mảng này.

+1

Cảm ơn lời giải thích đơn giản. – napender

1

Giá trị của biến CONSTANT_ARRAY không thể thay đổi. Biến đó chứa một mảng (tham chiếu đến một). Tuy nhiên, nội dung của mảng có thể thay đổi. Điều tương tự cũng xảy ra khi bạn khai báo bất kỳ loại biến cuối cùng nào không phải là một loại vô hướng đơn giản (ví dụ: một đối tượng).

Hãy cẩn thận cách bạn đặt tên biến của mình. :-) Gọi nó là CONSTANT_ARRAY không làm cho nội dung của mảng không thay đổi được.

Đây là một tài liệu tham khảo tốt: The final word on final

2

cuối cùng chỉ đảm bảo tính bất biến của nguyên thủy. Và cũng đảm bảo rằng một biến được chỉ định một lần. Nếu một đối tượng có thể thay đổi, bạn có thể thay đổi nội dung của sự kiện được xác định là đối tượng cuối cùng. Bạn có thể kiểm tra các bộ sưu tập bất biến cho nhu cầu của bạn. Chẳng hạn như Collections.unmodifiableList() http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#unmodifiableList(java.util.List)

+2

Không phải câu thứ hai ngụ ý – delnan

+0

Không. Một biến có thể tham chiếu đến một tham chiếu đối tượng, không nhất thiết phải là mồi itive. – afsina

+1

Vâng, vậy thì sao? Các biến là các biến, bất kể chúng là kiểu nguyên thủy hay kiểu tham chiếu. Và trong cả hai trường hợp, nó không thể được phân công lại. – delnan

13

Bạn đang hiểu sai việc triển khai cuối cùng.final áp dụng cho tham chiếu đối tượng mảng, có nghĩa là khi nó được khởi tạo, tham chiếu có thể không bao giờ thay đổi nhưng mảng của nó có thể được điền. "Nó không vi phạm các quy tắc" bạn đã chỉ định một quy tắc về thay đổi tham chiếu đang hoạt động phù hợp. Nếu bạn muốn các giá trị cũng nên bao giờ thay đổi, bạn nên đi cho danh sách Immutable tức

List<String> items = Collections.unmodifiableList(Arrays.asList("I", "can", "never", "change")); 
2

Các tham chiếu đến đối tượng mảng là cuối cùng (không thể thay đổi ví dụ như trong trường hợp bạn sẽ cố gắng để kết hợp một đối tượng mảng Java khác nhau (ví dụ của String []) cho cùng một biến cuối cùng ... bạn sẽ nhận được một lỗi thời gian biên dịch).

NHƯNG các trường của đối tượng mảng cuối cùng trong ví dụ của bạn không phải là cuối cùng và vì vậy bạn có thể sửa đổi giá trị của chúng. ... trong khi đối tượng Java bạn đã tạo, CONSTANT_ARRAY, sau khi nhận được giá trị ban đầu, sẽ có giá trị "mãi mãi" == cho đến khi JVM dừng. :) Nó sẽ là cùng một mảng String Array "mãi mãi".

Biến cuối cùng trong Java không phải là một vấn đề lớn, chỉ cần dành một chút thời gian để tiêu hóa chủ đề/ý tưởng một cách cẩn thận. :-)
Tôi đề nghị cho tất cả những người không chắc chắn thiền định trên trang này, ví dụ: https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4

Hãy để tôi trích dẫn một phần tương ứng:

" Khi một biến thức đã được Nếu một biến cuối cùng giữ một tham chiếu đến một đối tượng, thì trạng thái của đối tượng có thể được thay đổi bởi các hoạt động trên đối tượng, nhưng biến sẽ luôn luôn tham chiếu đến cùng một đối tượng. Điều này cũng áp dụng cho mảng, vì mảng là các đối tượng; nếu một biến cuối cùng giữ một tham chiếu đến một mảng, thì các thành phần của mảng có thể được thay đổi bởi các hoạt động trên mảng, nhưng biến sẽ luôn luôn tham chiếu đến cùng một mảng. "

0
final int[] res; 
    int[] res1; 
    int[] res2 = new int[1]; 
    res2[0]=20; 

    res1=res2; 
    res1=res2;//no error 
    System.out.println("res1:"+res1[0]); 

    res = res2;//only once 
    //res = res2;//error already initialised 
    res2[0]=30; 

    System.out.println("res:"+res[0]);  

sản lượng :: res1: 20 res: 30

+1

Đăng một đoạn mã không thực sự phù hợp với tinh thần tràn ngăn xếp. Vui lòng trả lời bằng nội dung, ngữ cảnh và chi tiết. – Gyan

Các vấn đề liên quan