Tạo đối số phương thức java là cuối cùng


92

Sự khác biệt nào finaltạo nên sự khác biệt giữa đoạn mã dưới đây. Có lợi thế nào trong việc khai báo các đối số như final.

public String changeTimezone( Timestamp stamp, Timezone fTz, Timezone toTz){  
    return ....
}

public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
        final Timezone toTz){
    return ....
}

4
Có bộ phân tích mã cảnh báo nếu một tham số được sử dụng lại hoặc chỉ định lại. (Tương tự cho các biến cục bộ) IMHO, Đây là cách tốt hơn để bắt các tham số như vậy nếu bạn thấy việc thay đổi chúng là không thể thực hiện được.
Peter Lawrey


Tôi cảm thấy Java nên đặt tất cả các đối số phương thức nhập là cuối cùng theo mặc định. Và sau đó nếu tôi muốn sửa đổi tham chiếu, tôi sẽ phải làm điều đó theo cách thủ công. Bằng cách đó, yếu tố tội lỗi sẽ ngăn chặn nhiều trường hợp như vậy.
Sid

Câu trả lời:


131

Vì một tham số phương thức chính thức là một biến cục bộ, bạn có thể truy cập chúng từ các lớp ẩn danh bên trong chỉ khi chúng được khai báo là cuối cùng.

Điều này giúp bạn không phải khai báo một biến cuối cùng cục bộ khác trong thân phương thức:

 void m(final int param) {
        new Thread(new Runnable() {
            public void run() {
                System.err.println(param);
            }
        }).start();
    }

27
+1: Đây là một trường hợp sử dụng quan trọng và là thời điểm duy nhất khi bạn cần . (Phần thời gian còn lại chỉ là vấn đề về những gì thuận tiện cho việc trợ giúp lập trình viên.)
Donal Fellows

3
Tôi có thể hỏi lý do đằng sau điều này?
KodeWarrior

21
Không cần thiết hơn với Java 8.
Amit Parashar

3
@simgineer đọc ở đây: stackoverflow.com/questions/28408109/…
PeterMmm,

3
@AmitParashar Đúng, nhưng Java 8 chỉ giúp bạn không phải sử dụng từ khóa "cuối cùng" mỗi khi bạn phải sử dụng biến trong lớp bên trong ... Thực tế là trình biên dịch chỉ đơn thuần làm cho tính cuối cùng ẩn, bạn vẫn cần biến cuối cùng có hiệu quả ... Vì vậy, bạn vẫn gặp lỗi thời gian biên dịch trong trường hợp bạn cố gắng gán cho nó sau này! Java 8 : SNEAK 100 :)
varun

38

Trích từ Lời cuối cùng trên từ khóa cuối cùng

Tham số cuối cùng

Mẫu sau khai báo các tham số cuối cùng:

public void doSomething(final int i, final int j)
{
  // cannot change the value of i or j here...
  // any change would be visible only inside the method...
}

Cuối cùng được sử dụng ở đây để đảm bảo hai chỉ mục i và j sẽ không vô tình bị đặt lại bởi phương thức này. Đó là một cách tiện dụng để bảo vệ khỏi một lỗi ngấm ngầm làm thay đổi sai giá trị của các tham số của bạn. Nói chung, các phương thức ngắn là cách tốt hơn để bảo vệ khỏi lớp lỗi này, nhưng các tham số cuối cùng có thể là một bổ sung hữu ích cho phong cách viết mã của bạn.

Lưu ý rằng các tham số cuối cùng không được coi là một phần của chữ ký phương thức và bị trình biên dịch bỏ qua khi giải quyết các cuộc gọi phương thức. Các tham số có thể được khai báo cuối cùng (hoặc không) mà không ảnh hưởng đến cách phương thức được ghi đè.


18
Có thể tốt hơn khi sử dụng các đối tượng hơn là các nguyên thủy cho ví dụ này, vì các thay đổi nguyên thủy sẽ luôn chỉ hiển thị bên trong phương thức. Và trong trường hợp đối tượng, bạn vẫn có thể thay đổi chúng. Bạn không thể chỉ vào một đối tượng mới. Thực tế bây giờ tôi nghĩ về nó, cuối cùng không thực sự thay đổi bất cứ điều gì so với việc bỏ nó ra, ngoài việc lưu một khai báo biến với AIC và để trình biên dịch chỉ ra các sửa đổi ngẫu nhiên của các tham số mà bạn không muốn sửa đổi vì lý do nào đó .
Rob Grant

27

Cuối cùng ngăn bạn gán giá trị mới cho biến và điều này có thể hữu ích trong việc sửa lỗi chính tả. Về mặt phong cách, bạn có thể muốn giữ nguyên các tham số đã nhận và chỉ gán cho các biến cục bộ, vì vậy, cuối cùng sẽ giúp thực thi phong cách đó.

Phải thừa nhận rằng tôi hiếm khi nhớ sử dụng cuối cùng cho các tham số, có lẽ tôi nên.

public int example(final int basicRate){
    int discountRate;

    discountRate = basicRate - 10;
    // ... lots of code here 
    if ( isGoldCustomer ) {
        basicRate--;  // typo, we intended to say discountRate--, final catches this
    }
    // ... more code here

    return discountRate;
}

1
Ví dụ tuyệt vời về cách khai báo các đối số là cuối cùng có thể hữu ích. Tôi là một phần của điều này nhưng họ cũng là một người thích thú với hơn 3 thông số.
JoseHdez_2

14

Nó không tạo ra nhiều khác biệt. Nó chỉ có nghĩa là bạn không thể viết:

stamp = null;
fTz = new ...;

nhưng bạn vẫn có thể viết:

stamp.setXXX(...);
fTz.setXXX(...);

Nó chủ yếu là một gợi ý cho lập trình viên bảo trì theo bạn rằng bạn sẽ không gán giá trị mới cho tham số ở đâu đó ở giữa phương thức của bạn, nơi nó không rõ ràng và do đó có thể gây nhầm lẫn.


3

Từ khóa cuối cùng khi được sử dụng cho các tham số / biến trong Java đánh dấu tham chiếu là cuối cùng. Trong trường hợp truyền một đối tượng cho một phương thức khác, hệ thống sẽ tạo một bản sao của biến tham chiếu và chuyển nó cho phương thức. Bằng cách đánh dấu các tham chiếu mới là cuối cùng, bạn bảo vệ chúng khỏi việc chỉ định lại. Đôi khi nó được coi là một thực hành mã hóa tốt.


1
Tôi phải thêm một cái gì đó: nếu các tham số là nguyên thủy, tôi không thấy bất kỳ sự khác biệt nào. Ngoài ra, nếu các tham số là Bộ sưu tập (danh sách các đối tượng ...), việc thêm cuối cùng sẽ không thể ngăn chúng bị sửa đổi.
Sam003,

1
Tính bất biến luôn là một đặc điểm đáng mơ ước. Java không có nó ra khỏi hộp. Làm cho các biến cuối cùng ít nhất đảm bảo tính toàn vẹn của tham chiếu.
Sid

1
Tôi đồng ý. Nhưng nếu chúng ta thực sự muốn đạt được tính bất biến cho các đối tượng, chúng ta có thể thử tạo một bản sao sâu.
Sam003,

2

Đối với phần thân của phương thức này, finaltừ khóa sẽ ngăn các tham chiếu đối số vô tình được gán lại gây ra lỗi biên dịch trong những trường hợp đó (hầu hết các IDE sẽ khiếu nại ngay lập tức). Một số người có thể tranh luận rằng việc sử dụng finalnói chung bất cứ khi nào có thể sẽ tăng tốc mọi thứ nhưng đó không phải là trường hợp trong các JVM gần đây.


2

Hai ưu điểm mà tôi thấy được liệt kê:

1 Đánh dấu đối số phương thức là cuối cùng ngăn cản việc gán lại đối số bên trong phương thức

Từ bạn ví dụ

    public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
            final Timezone toTz){
    
    // THIS WILL CAUSE COMPILATION ERROR as fTz is marked as final argument

      fTz = Calendar.getInstance().getTimeZone();     
      return ..
    
    }

Trong một phương pháp phức tạp, việc đánh dấu các đối số là cuối cùng sẽ giúp giải thích tình cờ các đối số này dưới dạng các biến cục bộ của phương thức và việc gán lại dưới dạng trình biên dịch sẽ gắn cờ các trường hợp này như được hiển thị trong ví dụ.

2 Truyền đối số cho một lớp bên trong ẩn danh

Vì một tham số phương thức chính thức là một biến cục bộ, bạn có thể truy cập chúng từ các lớp ẩn danh bên trong chỉ khi chúng được khai báo là cuối cùng.


1

- Trong quá khứ (trước Java 8 :-))

Giải thích việc sử dụng từ khóa "cuối cùng" ảnh hưởng đến khả năng truy cập của biến phương thức cho các lớp ẩn danh nội bộ.

- Trong ngôn ngữ hiện đại (Java 8+) không cần sử dụng như vậy:

Java đã giới thiệu các biến "cuối cùng hiệu quả". Các biến cục bộ và tham số phương thức được giả định là cuối cùng nếu mã không ngụ ý thay đổi giá trị của biến. Vì vậy, nếu bạn thấy từ khóa như vậy trong Java8 +, bạn có thể cho rằng nó là không cần thiết. Giới thiệu về "hiệu quả cuối cùng" khiến chúng ta gõ ít mã hơn khi sử dụng lambdas.


0

Nó chỉ là một cấu trúc trong Java để giúp bạn xác định hợp đồng và gắn bó với nó. Một cuộc thảo luận tương tự ở đây: http://c2.com/cgi/wiki?JavaFinalConsideredEvil

BTW - (như twiki nói), đánh dấu args là cuối cùng nói chung là thừa nếu bạn đang tuân theo các nguyên tắc lập trình tốt và do đó đã thực hiện gán lại / xác định lại tham chiếu đối số đến.

Trong trường hợp xấu nhất, nếu bạn xác định lại tham chiếu args, nó sẽ không ảnh hưởng đến giá trị thực được truyền vào hàm - vì chỉ có một tham chiếu được chuyển.


0

Tôi đang nói về việc đánh dấu các biến và trường cuối cùng nói chung - không chỉ áp dụng cho các đối số của phương thức. (Đánh dấu các phương thức / lớp cuối cùng là một điều hoàn toàn khác).

Đó là một ưu ái cho người đọc / người bảo trì mã của bạn trong tương lai. Cùng với một tên hợp lý của biến, sẽ hữu ích và khiến người đọc mã của bạn yên tâm khi xem / hiểu các biến được đề cập đại diện cho điều gì - và khiến người đọc yên tâm rằng bất cứ khi nào bạn nhìn thấy biến trong cùng một phạm vi, ý nghĩa vẫn giống nhau, vì vậy (các) anh ta không phải vò đầu bứt tai để luôn tìm ra ý nghĩa của một biến trong mọi ngữ cảnh. Chúng tôi đã thấy quá nhiều việc lạm dụng "sử dụng lại" các biến, điều này khiến ngay cả một đoạn mã ngắn cũng khó hiểu.


-3

Từ khóa cuối cùng ngăn bạn gán giá trị mới cho tham số. Tôi muốn giải thích điều này bằng một ví dụ đơn giản

Giả sử chúng ta có một phương pháp

method1 () {

Date dateOfBirth = new Date ("1/1/2009");

method2 (dateOfBirth);

method3 (dateOfBirth); }

public mehod2 (Date dateOfBirth) {
....
....
....
}

public mehod2 (Date dateOfBirth) {
....
....
....
}

Trong trường hợp trên nếu "dateOfBirth" được gán giá trị mới trong method2 hơn giá trị này sẽ dẫn đến kết quả sai từ method3. Vì giá trị đang được chuyển cho phương thức3 không phải là giá trị trước khi được chuyển cho phương thức2. Vì vậy, để tránh từ khóa cuối cùng này được sử dụng cho các tham số.

Và đây cũng là một trong những phương pháp hay nhất về lập trình Java.


5
Điều đó không hoàn toàn đúng. Ngay cả khi đối số dateOfBirth được thay đổi thành giá trị khác trong method2 (), điều này sẽ không ảnh hưởng đến method2 (), vì Java chuyển theo giá trị chứ không phải tham chiếu.
Flo
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.