Khi nào nên sử dụng cuối cùng cho các tham số phương thức và các biến cục bộ?


171

Tôi đã tìm thấy một vài tài liệu tham khảo ( ví dụ ) đề xuất sử dụng finalcàng nhiều càng tốt và tôi tự hỏi điều đó quan trọng như thế nào. Điều này chủ yếu là trong bối cảnh của các tham số phương thức và các biến cục bộ, không phải là các phương thức hoặc các lớp cuối cùng. Đối với hằng số, nó có ý nghĩa rõ ràng.

Một mặt, trình biên dịch có thể thực hiện một số tối ưu hóa và nó làm cho ý định của lập trình viên rõ ràng hơn. Mặt khác, nó thêm tính dài dòng và tối ưu hóa có thể là tầm thường.

Nó có phải là một cái gì đó tôi nên cố gắng ghi nhớ?


Đây là một bài viết liên quan để xem qua: stackoverflow.com/questions/137868/ cấp
mattlant


1
Tôi nâng cấp chỉ vì tôi không biết rằng có thể sử dụng cuối cùng như một công cụ sửa đổi trên các tham số trước khi đọc điều này. Cảm ơn!
Kip

Câu trả lời:


178

Ám ảnh:

  • Các trường cuối cùng - Đánh dấu các trường là cuối cùng buộc chúng phải được đặt khi kết thúc xây dựng, làm cho tham chiếu trường đó không thay đổi. Điều này cho phép xuất bản các trường an toàn và có thể tránh sự cần thiết phải đồng bộ hóa trong các lần đọc sau. (Lưu ý rằng đối với tham chiếu đối tượng, chỉ tham chiếu trường là bất biến - những điều mà tham chiếu đối tượng đề cập đến vẫn có thể thay đổi và điều đó ảnh hưởng đến tính bất biến.)
  • Các trường tĩnh cuối cùng - Mặc dù bây giờ tôi sử dụng enums cho nhiều trường hợp tôi đã sử dụng các trường tĩnh cuối cùng.

Cân nhắc nhưng sử dụng thận trọng:

  • Các lớp cuối cùng - Thiết kế khung / API là trường hợp duy nhất mà tôi xem xét nó.
  • Phương thức cuối cùng - Về cơ bản giống như các lớp cuối cùng. Nếu bạn đang sử dụng các mẫu phương thức mẫu như điên và đánh dấu thứ cuối cùng, có lẽ bạn phụ thuộc quá nhiều vào tính kế thừa và không đủ cho việc ủy ​​quyền.

Bỏ qua trừ khi cảm thấy hậu môn:

  • Các tham số của phương thức và các biến cục bộ - Tôi RARELY làm điều này phần lớn vì tôi lười biếng và tôi thấy nó làm tắc mã. Tôi sẽ hoàn toàn thừa nhận rằng việc đánh dấu các tham số và các biến cục bộ mà tôi sẽ không sửa đổi là "sáng hơn". Tôi ước nó là mặc định. Nhưng nó không phải là và tôi thấy mã khó hiểu hơn với trận chung kết. Nếu tôi đang ở trong mã của người khác, tôi sẽ không rút chúng ra nhưng nếu tôi viết mã mới, tôi sẽ không đưa chúng vào. Một ngoại lệ là trường hợp bạn phải đánh dấu thứ gì đó cuối cùng để bạn có thể truy cập nó từ bên trong một lớp bên trong vô danh.

  • Chỉnh sửa: lưu ý rằng một trường hợp sử dụng trong đó các biến cục bộ cuối cùng thực sự rất hữu ích như được đề cập bởi @ adam-gent là khi giá trị được gán cho var trong if/ elsenhánh.


8
Joshua Bloch lập luận rằng tất cả các lớp nên được định nghĩa là cuối cùng, trừ khi chúng được thiết kế để kế thừa. Tôi đồng ý với anh ấy; Tôi thêm cuối cùng vào mỗi lớp thực hiện một giao diện (để có thể tạo các bài kiểm tra đơn vị). Đồng thời đánh dấu là cuối cùng tất cả các phương thức được bảo vệ / lớp, sẽ không bị ghi đè.
rmaruszewski

61
Với tất cả sự tôn trọng dành cho Josh Bloch (và đó là một số tiền đáng kể), tôi không đồng ý với trường hợp chung. Trong trường hợp xây dựng API, hãy chắc chắn khóa mọi thứ. Bùi bên trong mã của riêng bạn, dựng lên những bức tường mà sau này bạn phải phá bỏ là một sự lãng phí thời gian.
Alex Miller

9
Nó chắc chắn không phải là "lãng phí thời gian", đặc biệt vì nó hoàn toàn không tốn thời gian ... Trong một ứng dụng, tôi thường tạo ra hầu hết tất cả các lớp finaltheo mặc định. Mặc dù vậy, bạn có thể không nhận thấy các lợi ích trừ khi bạn sử dụng IDE Java thực sự hiện đại (ví dụ: IDEA).
Rogério

9
IDEA có (ngoài hộp) hàng trăm kiểm tra mã và một số trong số đó có thể phát hiện mã không sử dụng / không cần thiết trong finalcác lớp / phương thức. Ví dụ: nếu một phương thức cuối cùng tuyên bố ném một ngoại lệ được kiểm tra nhưng thực sự không bao giờ ném nó, IDEA sẽ cho bạn biết điều đó và bạn có thể xóa ngoại lệ khỏi throwsmệnh đề. Đôi khi, bạn cũng có thể tìm thấy toàn bộ các phương thức không được sử dụng, có thể phát hiện được khi chúng không thể bị ghi đè.
Rogério

8
@rmaruszewski Đánh dấu các lớp là cuối cùng ngăn hầu hết các khung mô phỏng không thể chế nhạo chúng, do đó làm cho mã của bạn khó kiểm tra hơn. Tôi sẽ chỉ làm một trận chung kết lớp nếu nó cực kỳ quan trọng mà nó không được gia hạn.
Mike Rylander

44

Đó có phải là điều tôi nên cố gắng ghi nhớ để làm không?

Không, nếu bạn đang sử dụng Eclipse, bởi vì bạn có thể định cấu hình Lưu hành động để tự động thêm các sửa đổi cuối cùng này cho bạn. Sau đó, bạn nhận được những lợi ích cho nỗ lực ít hơn.


3
Mẹo hay với Save Action, không biết về điều đó.
sự tỉnh táo

1
Tôi chủ yếu xem xét lợi ích cuối cùng làm cho mã an toàn hơn khỏi các lỗi bằng cách vô tình gán sai biến, thay vì bất kỳ tối ưu hóa nào có thể hoặc không thể xảy ra.
Peter Hilton

4
Đây thực sự là một vấn đề cho bạn? Bạn có thường xuyên gặp phải một lỗi phát sinh từ việc này không?
Alex Miller

1
+1 cho mẹo hữu ích trong Eclipse. Tôi nghĩ rằng chúng ta nên sử dụng cuối cùng càng nhiều càng tốt để tránh lỗi.
emeraldhieu

Bạn có thể làm điều này trong IntelliJ không?
Koray Tugay

15

Các lợi ích trong thời gian phát triển của "cuối cùng" ít nhất cũng quan trọng như các lợi ích trong thời gian chạy. Nó nói với các biên tập viên tương lai của mã một cái gì đó về ý định của bạn.

Đánh dấu một lớp "cuối cùng" cho thấy rằng bạn đã không nỗ lực trong quá trình thiết kế hoặc triển khai lớp để xử lý mở rộng một cách duyên dáng. Nếu người đọc có thể thay đổi lớp và muốn xóa công cụ sửa đổi "cuối cùng", họ có thể tự chịu rủi ro. Tùy thuộc vào họ để đảm bảo rằng lớp sẽ xử lý tốt phần mở rộng.

Đánh dấu một biến "cuối cùng" (và gán nó trong hàm tạo) là hữu ích với phép nội xạ phụ thuộc. Nó chỉ ra bản chất "cộng tác viên" của biến.

Đánh dấu một phương thức "cuối cùng" là hữu ích trong các lớp trừu tượng. Nó mô tả rõ ràng nơi các điểm mở rộng.


11

Tôi sử dụng finaltất cả thời gian để làm cho Java có nhiều biểu thức hơn. Xem các điều kiện của Java ( if,else,switch) không phải là biểu thức mà tôi luôn ghét đặc biệt là nếu bạn đã sử dụng để lập trình chức năng (ví dụ ML, Scala hoặc Lisp).

Vì vậy, bạn nên cố gắng luôn luôn (IMHO) sử dụng các biến cuối cùng khi sử dụng điều kiện.

Tôi sẽ cho bạn một ví dụ:

    final String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
        default:
            throw new IllegalStateException();
    }

Bây giờ Nếu thêm một casecâu lệnh khác và không đặt nametrình biên dịch sẽ thất bại. Trình biên dịch cũng sẽ thất bại nếu bạn không phá vỡ mọi trường hợp (mà bạn đặt biến). Điều này cho phép bạn làm cho Java rất giống với các letbiểu thức của Lisp và làm cho nó để mã của bạn không bị thụt vào ồ ạt (vì các biến phạm vi từ vựng).

Và như @Recurse đã lưu ý (nhưng rõ ràng là -1 tôi), bạn có thể thực hiện điều đó trước khi thực hiện String name finalđể nhận lỗi trình biên dịch (mà tôi không bao giờ nói là không thể) nhưng bạn có thể dễ dàng khiến lỗi trình biên dịch biến mất tên thiết lập sau khi chuyển đổi câu lệnh loại bỏ ngữ nghĩa biểu thức hoặc tệ hơn là quên breakmà bạn không thể gây ra lỗi (bất chấp những gì @Recurse nói) mà không sử dụng final:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            //break; whoops forgot break.. 
            //this will cause a compile error for final ;P @Recurse
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

Do tên thiết lập lỗi (ngoài việc quên mất breakđó cũng là một lỗi khác), giờ đây tôi có thể vô tình làm điều này:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        //should have handled all the cases for pluginType
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

Biến cuối cùng buộc một đánh giá duy nhất về tên nên là gì. Tương tự như cách một hàm có giá trị trả về phải luôn trả về một giá trị (bỏ qua các ngoại lệ), khối chuyển đổi tên sẽ phải phân giải tên và do đó ràng buộc với khối chuyển đổi đó giúp tái cấu trúc các đoạn mã dễ dàng hơn (ví dụ phương thức chiết xuất Eclipe: phương thức trích xuất) .

Những điều trên trong OCaml:

type plugin = CandidateExport | JobPostingImport

let p = CandidateExport

let name = match p with
    | CandidateExport -> "Candidate Stuff"
    | JobPostingImport -> "Blah" ;;

Các match ... with ...đánh giá như một hàm tức là biểu thức. Lưu ý rằng nó trông giống như tuyên bố chuyển đổi của chúng tôi.

Dưới đây là một ví dụ trong Lược đồ (Vợt hoặc Gà):

(define name 
    (match b
      ['CandidateExport "Candidate Stuff"]
      ['JobPostingImport "Blah"]))

1
Ngoại trừ việc trình biên dịch java sẽ cung cấp cho bạn một lỗi "tên có khả năng chưa được khởi tạo" và từ chối biên dịch có hoặc không có bản cuối cùng.
Tái diễn

4
Có nhưng với trận chung kết bạn có thể thiết lập lại bất cứ lúc nào. Tôi thực sự đã thấy điều này xảy ra khi một nhà phát triển biến else if (...)thành một if(...)và do đó đặt lại biến. Tôi đã cho anh ta thấy rằng sẽ không bao giờ xảy ra với một biến cuối cùng. Về cơ bản finalbuộc bạn phải gán biến một lần và chỉ một lần ... vì vậy: P
Adam Gent

9

Tôi đã tìm thấy các tham số phương thức và địa phương finalhữu ích như là một trợ giúp tái cấu trúc khi phương thức được đề cập là một mớ hỗn độn khó hiểu trong nhiều trang dài. Rắc rắc finalmột cách tự do, xem những lỗi "không thể gán cho biến cuối cùng" mà trình biên dịch (hoặc IDE của bạn) đưa ra và bạn có thể khám phá lý do tại sao biến được gọi là "dữ liệu" kết thúc bằng null mặc dù một số bình luận (lỗi thời) có thể thề Sẽ xảy ra.

Sau đó, bạn có thể sửa một số lỗi bằng cách thay thế các biến được sử dụng lại bằng các biến mới được khai báo gần hơn với điểm sử dụng. Sau đó, bạn thấy rằng bạn có thể bao bọc toàn bộ các phần của phương thức trong các dấu ngoặc nhọn, và đột nhiên bạn là một phím bấm IDE từ "Phương pháp trích xuất" và quái vật của bạn trở nên dễ hiểu hơn.

Nếu phương pháp của bạn chưa phải là một xác tàu không thể xác định được, tôi đoán có thể có giá trị trong việc đưa ra công cụ cuối cùng để ngăn cản mọi người biến nó thành xác tàu nói trên; nhưng nếu đó là một phương pháp ngắn (xem: không phải là không thể hiểu được) thì bạn có nguy cơ thêm rất nhiều tính dài dòng. Cụ thể, chữ ký hàm Java đủ cứng để phù hợp với 80 ký tự như vậy mà không cần thêm sáu ký tự cho mỗi đối số!


1
Điểm cuối rất hợp lệ, mặc dù tôi đã từ bỏ giới hạn 80 ký tự từ lâu vì độ phân giải màn hình đã thay đổi một chút trong 10 năm qua. Tôi có thể dễ dàng điều chỉnh một dòng 300 char trên màn hình của mình mà không cần cuộn. Tuy nhiên, khả năng đọc tất nhiên là tốt hơn mà không cần finaltrước mỗi tham số.
brimborium

8

Chà, tất cả phụ thuộc vào phong cách của bạn ... nếu bạn THÍCH xem trận chung kết khi bạn sẽ không sửa đổi biến, thì hãy sử dụng nó. Nếu bạn KHÔNG THÍCH nhìn thấy nó ... thì hãy bỏ nó đi.

Cá nhân tôi thích càng ít chi tiết càng tốt, vì vậy tôi có xu hướng tránh sử dụng các từ khóa bổ sung không thực sự cần thiết.

Mặc dù vậy, tôi thích ngôn ngữ động hơn, vì vậy có lẽ không có gì ngạc nhiên khi tôi muốn tránh sự dài dòng.

Vì vậy, tôi sẽ nói chỉ cần chọn hướng bạn đang nghiêng và chỉ cần đi với nó (bất kể trường hợp nào, hãy cố gắng nhất quán).


Một lưu ý phụ, tôi đã làm việc trên các dự án vừa sử dụng vừa không sử dụng một mẫu như vậy và tôi đã thấy không có sự khác biệt về số lượng lỗi hoặc lỗi ... Tôi không nghĩ rằng đó là một mẫu sẽ cực kỳ cải thiện số lượng lỗi của bạn hoặc bất cứ điều gì, nhưng một lần nữa, đó là phong cách và nếu bạn muốn thể hiện ý định mà bạn sẽ không sửa đổi nó, thì hãy tiếp tục và sử dụng nó.


6

Nó rất hữu ích trong các tham số để tránh thay đổi giá trị tham số một cách tình cờ và đưa ra một lỗi tinh vi. Tôi sử dụng để bỏ qua khuyến nghị này nhưng sau khi dành khoảng 4 giờ. trong một phương thức khủng khiếp (với hàng trăm dòng mã và nhiều fors, ifs lồng nhau và tất cả các loại thực hành xấu) tôi sẽ khuyên bạn nên làm điều đó.

 public int processSomethingCritical( final int x, final int y ){
 // hundreds of lines here 
     // for loop here...
         int x2 = 0;
        x++; // bug aarrgg...
 // hundreds of lines there
 // if( x == 0 ) { ...

 }

Tất nhiên trong một thế giới hoàn hảo, điều này sẽ không xảy ra, nhưng .. tốt .. đôi khi bạn phải hỗ trợ mã người khác. :


2
Phương pháp này có nhiều vấn đề nghiêm trọng hơn thiếu cuối cùng. Mặc dù điều này không phổ biến, mặc dù không phải là không thể, rằng có một lý do chính đáng để một phương pháp trở nên lộn xộn đến mức những loại lỗi này sẽ xảy ra. Một chút suy nghĩ đặt vào tên biến sẽ đi một chặng đường dài đối với các tai nạn như thế này.
ykaganovich

2
Nếu bạn có "hàng trăm dòng mã" trong một phương thức, bạn có thể muốn chia nó thành nhiều phương thức nhỏ hơn.
Steve Kuo

5

Nếu bạn đang viết một ứng dụng mà ai đó sẽ phải đọc mã sau, giả sử, 1 năm, sau đó, hãy sử dụng cuối cùng trên biến không nên sửa đổi mọi lúc. Bằng cách này, mã của bạn sẽ "tự ghi lại" hơn và bạn cũng giảm cơ hội cho các nhà phát triển khác làm những việc ngớ ngẩn như sử dụng hằng số cục bộ làm biến tạm thời cục bộ.

Nếu bạn đang viết một số mã vứt đi, thì, đừng bận tâm xác định tất cả các hằng số và biến chúng thành cuối cùng.


4

Tôi sẽ sử dụng cuối cùng nhiều nhất có thể. Làm như vậy sẽ gắn cờ nếu bạn vô tình thay đổi trường. Tôi cũng đặt tham số Phương thức thành cuối cùng. Làm như vậy tôi đã bắt được một số lỗi từ mã mà tôi đã xử lý khi họ cố gắng 'đặt' một tham số mà quên Java truyền theo giá trị.


2

Vẫn chưa rõ câu hỏi liệu điều này có rõ ràng hay không, nhưng việc đưa ra một tham số phương thức cuối cùng chỉ ảnh hưởng đến phần thân của phương thức. Nó KHÔNG truyền đạt bất kỳ thông tin thú vị nào về ý định của phương thức cho kẻ xâm lược. Đối tượng được truyền vào vẫn có thể bị đột biến trong phương thức (chung kết không phải là hằng số) và phạm vi của biến nằm trong phương thức.

Để trả lời câu hỏi chính xác của bạn, tôi sẽ không làm cho một cá thể hoặc biến cục bộ (bao gồm các tham số phương thức) cuối cùng trừ khi mã yêu cầu nó (ví dụ: biến được tham chiếu từ một lớp bên trong) hoặc để làm rõ một số logic thực sự phức tạp.

Đối với các biến thể hiện, tôi sẽ làm cho chúng cuối cùng nếu chúng là hằng số logic.


2

Có nhiều cách sử dụng cho biến final. Đây chỉ là một vài

Hằng số cuối cùng

 public static class CircleToolsBetter {
     public final static double PI = 3.141;
        public double getCircleArea(final double radius) {
          return (Math.pow(radius, 2) * PI);
        }
    }

Điều này có thể được sử dụng sau đó cho các phần khác của mã của bạn hoặc được các lớp khác truy cập, theo cách đó nếu bạn thay đổi giá trị, bạn sẽ không phải thay đổi từng cái một.

Biến cuối cùng

public static String someMethod(final String environmentKey) {
    final String key = "env." + environmentKey;
    System.out.println("Key is: " + key);
    return (System.getProperty(key));

  }

}

Trong lớp này, bạn xây dựng một biến cuối cùng có phạm vi có thêm tiền tố vào tham số môi trường. Trong trường hợp này, biến cuối cùng chỉ là cuối cùng trong phạm vi thực thi, khác nhau ở mỗi lần thực hiện của phương thức. Mỗi khi phương thức được nhập vào, trận chung kết sẽ được xây dựng lại. Ngay khi được xây dựng, nó không thể thay đổi trong phạm vi thực thi phương thức. Điều này cho phép bạn sửa một biến trong một phương thức trong suốt thời gian của phương thức. xem bên dưới:

public class FinalVariables {


  public final static void main(final String[] args) {
    System.out.println("Note how the key variable is changed.");
    someMethod("JAVA_HOME");
    someMethod("ANT_HOME");
  }
}

Hằng số cuối cùng

public double equation2Better(final double inputValue) {
    final double K = 1.414;
    final double X = 45.0;

double result = (((Math.pow(inputValue, 3.0d) * K) + X) * M);
double powInputValue = 0;         
if (result > 360) {
  powInputValue = X * Math.sin(result); 
} else {
  inputValue = K * Math.sin(result);   // <= Compiler error   
}

Điều này đặc biệt hữu ích khi bạn có các dòng mã thực sự dài và nó sẽ tạo ra lỗi trình biên dịch để bạn không gặp phải lỗi logic / nghiệp vụ khi ai đó vô tình thay đổi các biến không nên thay đổi.

Bộ sưu tập cuối cùng

Trường hợp khác nhau khi chúng ta đang nói về Bộ sưu tập, bạn cần đặt chúng là không thể thay đổi.

 public final static Set VALID_COLORS; 
    static {
      Set temp = new HashSet( );
      temp.add(Color.red);
      temp.add(Color.orange);
      temp.add(Color.yellow);
      temp.add(Color.green);
      temp.add(Color.blue);
      temp.add(Color.decode("#4B0082")); // indigo
      temp.add(Color.decode("#8A2BE2")); // violet
      VALID_COLORS = Collections.unmodifiableSet(temp);
    }

mặt khác, nếu bạn không đặt nó là không thể thay đổi:

Set colors = Rainbow.VALID_COLORS;
colors.add(Color.black); // <= logic error but allowed by compiler

Lớp cuối cùngPhương thức cuối cùng không thể được mở rộng hoặc ghi đè tương ứng.

EDIT: ĐỂ THÊM CÁC VẤN ĐỀ VỀ VẤN ĐỀ LỚP CUỐI CÙNG:

Có hai cách để làm cho một lớp cuối cùng. Đầu tiên là sử dụng từ khóa cuối cùng trong khai báo lớp:

public final class SomeClass {
  //  . . . Class contents
}

Cách thứ hai để thực hiện một trận chung kết lớp là khai báo tất cả các hàm tạo của nó là riêng tư:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

Đánh dấu nó cuối cùng giúp bạn tránh khỏi rắc rối nếu phát hiện ra rằng nó thực sự là một trận chung kết, để chứng minh cái nhìn về lớp Test này. nhìn công khai từ cái nhìn đầu tiên.

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

Thật không may, vì hàm tạo duy nhất của lớp là riêng tư, nên không thể mở rộng lớp này. Trong trường hợp của lớp Test, không có lý do gì mà lớp phải là cuối cùng. Lớp Test là một ví dụ tốt về cách các lớp cuối cùng ẩn có thể gây ra vấn đề.

Vì vậy, bạn nên đánh dấu nó là cuối cùng khi bạn ngầm hoàn thành một lớp cuối cùng bằng cách đặt nó ở chế độ riêng tư.


1

Một phần của sự đánh đổi như bạn đề cập, nhưng tôi thích sử dụng rõ ràng một cái gì đó hơn là sử dụng ngầm. Điều này sẽ giúp loại bỏ một số sự mơ hồ cho những người duy trì mã trong tương lai - ngay cả khi đó chỉ là bạn.


1

Nếu bạn có các lớp bên trong (ẩn danh) và phương thức cần truy cập biến của phương thức chứa, bạn cần phải có biến đó là biến cuối cùng.

Ngoài ra, những gì bạn đã nói là đúng.


Bây giờ java 8 cung cấp tính linh hoạt với các biến cuối cùng hiệu quả.
Ravindra babu

0

Sử dụng finaltừ khóa cho một biến nếu bạn đang biến biến đó thànhimmutable

Bằng cách khai báo biến là cuối cùng, nó hỗ trợ các nhà phát triển loại trừ các vấn đề sửa đổi có thể có của các biến trong môi trường đa luồng.

Với phiên bản java 8, chúng tôi có thêm một khái niệm gọi là " effectively final variable". Một biến không phải là cuối cùng có thể là biến cuối cùng.

các biến cục bộ được tham chiếu từ biểu thức lambda phải là cuối cùng hoặc cuối cùng có hiệu quả

Một biến được coi là hiệu lực cuối cùng nếu nó không được sửa đổi sau khi khởi tạo trong khối cục bộ. Điều này có nghĩa là bây giờ bạn có thể sử dụng biến cục bộ mà không cần từ khóa cuối cùng bên trong một lớp ẩn danh hoặc biểu thức lambda, miễn là chúng phải là cuối cùng một cách hiệu quả.

Cho đến Java 7, bạn không thể sử dụng biến cục bộ không phải là cuối cùng trong một lớp ẩn danh, nhưng từ Java 8, bạn có thể

Hãy xem bài viết này


-1

Trước hết, từ khóa cuối cùng được sử dụng để tạo một biến không đổi. Hằng có nghĩa là nó không thay đổi. Ví dụ:

final int CM_PER_INCH = 2.54;

Bạn sẽ khai báo biến cuối cùng vì một centimet trên inch không thay đổi.

Nếu bạn cố gắng ghi đè một giá trị cuối cùng, biến là giá trị được khai báo đầu tiên. Ví dụ:

final String helloworld = "Hello World";
helloworld = "A String"; //helloworld still equals "Hello World"

Có một lỗi biên dịch giống như:

local variable is accessed from inner class, must be declared final

Nếu biến của bạn không thể được khai báo cuối cùng hoặc nếu bạn không muốn khai báo biến cuối cùng, hãy thử điều này:

final String[] helloworld = new String[1];
helloworld[0] = "Hello World!";
System.out.println(helloworld[0]);
helloworld[0] = "A String";
System.out.println(helloworld[0]);

Điều này sẽ in:

Hello World!
A String
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.