Đối số cuối cùng trong phương thức giao diện - điểm gì?


189

Trong Java, việc định nghĩa các finalđối số trong các phương thức giao diện là hoàn toàn hợp pháp và không tuân theo điều đó trong lớp triển khai, ví dụ:

public interface Foo {
    public void foo(int bar, final int baz);
}

public class FooImpl implements Foo {

    @Override
    public void foo(final int bar, int baz) {
        ...
    }
}

Trong ví dụ trên, barbazcó các finalđịnh nghĩa ngược lại trong lớp VS giao diện.

Theo cùng một cách, không có finalhạn chế nào được thi hành khi một phương thức lớp mở rộng một phương thức khác, hoặc là abstractkhông.

Trong khi finalcó một số giá trị thực tế bên trong thân phương thức lớp, có điểm nào chỉ định finalcho các tham số phương thức giao diện không?


finaldù sao cũng không làm gì với kiểu bản địa, vì chúng được sao chép.
Paul Tomblin

11
Cũng giống như một điểm thảo luận: Tôi vừa thử nó và nếu hai interfaceđịnh nghĩa chỉ khác nhau về finalthuộc tính của một đối số, thì các .classtệp kết quả là byte theo từng byte (và dĩ nhiên javap -vtạo ra cùng một đầu ra). Điều này cũng đúng với hai lớp chỉ khác nhau finalvề một thuộc tính!
Joachim Sauer

2
@Paul: nó thực hiện chính xác giống như với các kiểu tham chiếu: nó ngăn chính các đối số được sửa đổi (nếu được sử dụng trong triển khai).
Joachim Sauer

Nó có liên quan nhiều như công chúng trong chữ ký phương thức.
Robin

2
@Deepak: Tôi thấy bạn yêu cầu làm ví dụ cho tất cả các loại câu hỏi, ngay cả khi nó dường như không có nhiều ý nghĩa. Tôi nghĩ bạn nên thử học một số suy nghĩ trừu tượng: thử suy nghĩ về một vấn đề mà không có một số mã thực thi trước mặt bạn. Nó sẽ giúp bạn rất nhiều trong thời gian dài.
Joachim Sauer

Câu trả lời:


103

Dường như không có bất kỳ điểm nào với nó. Theo Đặc tả ngôn ngữ Java 4.12.4 :

Khai báo một biến cuối cùng có thể đóng vai trò là tài liệu hữu ích mà giá trị của nó sẽ không thay đổi và có thể giúp tránh các lỗi lập trình.

Tuy nhiên, một công cụ finalsửa đổi trên một tham số phương thức không được đề cập trong các quy tắc khớp chữ ký của các phương thức bị ghi đè và nó không có tác dụng đối với người gọi, chỉ trong phần thân của một triển khai. Ngoài ra, như Robin đã lưu ý trong một nhận xét, công cụ finalsửa đổi trên tham số phương thức không ảnh hưởng đến mã byte được tạo. (Điều này không đúng với các mục đích sử dụng khác của final.)


Liệu tham số phương thức cũng đủ điều kiện là một biến? Nó rõ ràng là trong thực tế, nhưng nó là trong bối cảnh đặc điểm kỹ thuật?
mindas

11
Nó không thể được sử dụng để khớp chữ ký vì nó không xuất hiện trong tệp. Class thực tế. Nó chỉ dành cho trình biên dịch.
Robin

@mindas - JLS nói rằng có bảy loại biến . Phương thức paramaters là thứ tư trong danh sách.
Ted Hopp

3
Tài liệu bên cạnh vô dụng, tuy nhiên, vì công cụ finalsửa đổi không được thi hành trên lớp thực hiện. Chữ ký giao diện của bạn có thể chỉ đơn giản là nói dối.
Stefan Haberl

Thông số ngôn ngữ Java 8 bây giờ nói rằng có tám loại biến (tăng từ bảy - chúng đã thêm các tham số lambda ). Các tham số của phương thức vẫn đứng thứ tư trong danh sách (ít nhất một số thứ trong cuộc sống có vẻ ổn định. :-)).
Ted Hopp

25

Một số IDE sẽ sao chép chữ ký của phương thức trừu tượng / giao diện khi chèn một phương thức thực hiện trong một lớp con.

Tôi không tin rằng nó làm cho bất kỳ sự khác biệt với trình biên dịch.

EDIT: Mặc dù tôi tin rằng điều này là đúng trong quá khứ, tôi không nghĩ các IDE hiện tại làm điều này nữa.


2
Điểm hợp lệ, mặc dù tôi không nghĩ rằng có nhiều IDE khi tính năng này được triển khai (hoặc vô tình để lại) :-)
mindas

2
Tôi nghĩ là trong danh mục của static transientcác lĩnh vực. ;)
Peter Lawrey

1
Và các nhà xây dựng công cộng trên một lớp trừu tượng.
Peter Lawrey

1
IntelliJ làm điều này. Phiên bản của tôi là IntelliJ IDEA 2016.1.3 Build # IU-145.1617.
túc xá

1
@Dormouse, thật thú vị, vì Android Studio (3.1.4 Build # AI-173.4907809) không :(
Bố già

18

Các chú thích cuối cùng của các tham số phương thức luôn chỉ liên quan đến việc thực hiện phương thức không bao giờ cho người gọi. Do đó, không có lý do thực sự để sử dụng chúng trong chữ ký phương thức giao diện. Trừ khi bạn muốn tuân theo cùng một tiêu chuẩn mã hóa nhất quán, đòi hỏi các tham số phương thức cuối cùng, trong tất cả các chữ ký phương thức. Sau đó, nó là tốt đẹp để có thể làm như vậy.


6

Cập nhật: Câu trả lời gốc dưới đây được viết mà không hiểu đầy đủ câu hỏi và do đó không trực tiếp giải quyết câu hỏi :)Tuy nhiên, nó phải là thông tin cho những ai muốn tìm hiểu cách sử dụng chung của finaltừ khóa.

Đối với câu hỏi, tôi muốn trích dẫn nhận xét của riêng tôi từ bên dưới.

Tôi tin rằng bạn không bị buộc phải thực thi tính hữu hạn của một cuộc tranh luận để bạn tự do quyết định liệu nó có nên là cuối cùng hay không trong việc thực hiện của chính bạn.

Nhưng vâng, nghe có vẻ kỳ quặc khi bạn có thể khai báo nó finaltrong giao diện, nhưng nó không phải là cuối cùng trong việc thực hiện. Nó sẽ có ý nghĩa hơn nếu một trong hai:

a. finaltừ khóa không được phép cho các đối số phương thức giao diện (trừu tượng) (nhưng bạn có thể sử dụng nó trong triển khai) hoặc
b. khai báo một đối số như finaltrong giao diện sẽ buộc nó phải được khai báo finalkhi thực hiện (nhưng không bắt buộc đối với các trận chung kết).


Tôi có thể nghĩ ra hai lý do tại sao chữ ký phương thức có thể có finalcác tham số: ĐậuĐối tượng ( Trên thực tế, cả hai đều có cùng lý do, nhưng bối cảnh hơi khác nhau. )

Các đối tượng:

public static void main(String[] args) {
    StringBuilder cookingPot = new StringBuilder("Water ");
    addVegetables(cookingPot);
    addChicken(cookingPot);
    System.out.println(cookingPot.toString());
    // ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth 
    //      We forgot to add cauliflower. It went into the wrong pot.
}

private static void addVegetables(StringBuilder cookingPot) {
    cookingPot.append("Carrot ");
    cookingPot.append("Broccoli ");
    cookingPot = new StringBuilder(cookingPot.toString());
    //   ^--- Assignment allowed...
    cookingPot.append("Cauliflower ");
}

private static void addChicken(final StringBuilder cookingPot) {
    cookingPot.append("Chicken ");
    //cookingPot = new StringBuilder(cookingPot.toString());
    //     ^---- COMPILATION ERROR! It is final.
    cookingPot.append("ChickenBroth ");
}

Các finaltừ khóa đảm bảo rằng chúng tôi sẽ không vô tình tạo ra một mới địa phương nồi nấu ăn bằng cách hiển thị một lỗi biên dịch khi chúng tôi cố gắng làm như vậy. Điều này đảm bảo nước dùng gà được thêm vào nồi nấu ban đầu của chúng tôi mà addChickenphương pháp có được. So sánh điều này với addVegetablesnơi chúng tôi mất súp lơ vì nó đã thêm nó vào một nồi nấu địa phương mới thay vì nồi ban đầu mà nó có.

Đậu: Đó là khái niệm tương tự như các đối tượng (như được hiển thị ở trên) . Đậu chủ yếu Objectlà s trong Java. Tuy nhiên, các bean (JavaBeans) được sử dụng trong các ứng dụng khác nhau như một cách thuận tiện để lưu trữ và chuyển xung quanh một bộ sưu tập dữ liệu liên quan được xác định. Giống như việc addVegetablescó thể làm xáo trộn quá trình nấu ăn bằng cách tạo ra một nồi nấu mới StringBuildervà ném nó đi với súp lơ, nó cũng có thể làm tương tự với nồi nấu JavaBean .


Đồng ý. Đây thực sự không phải là một câu trả lời chính xác cho câu hỏi, (vì tôi không bị buộc phải thực hiện phương thức giao diện của mình lấy các đối số cuối cùng, ngay cả khi giao diện nói như vậy), nhưng nó vẫn hữu ích, đó là một lời giải thích tốt về lý do tại sao làm cho các tham số phương thức cuối cùng là một ý tưởng tốt để bắt đầu.
Phil

Tôi tin rằng bạn không bị buộc phải thực thi tính hữu hạn của một cuộc tranh luận để bạn tự do quyết định liệu nó có nên là cuối cùng hay không trong việc thực hiện của chính bạn. Nhưng vâng, nghe có vẻ kỳ quặc khi bạn có thể khai báo nó finaltrong giao diện, nhưng nó không phải là cuối cùng trong việc thực hiện. Sẽ có ý nghĩa hơn nếu một trong hai (a) final từ khóa không được phép cho các đối số phương thức giao diện (trừu tượng) (nhưng bạn có thể sử dụng nó trong triển khai) hoặc (b) khai báo một đối số như finaltrong giao diện sẽ buộc nó phải được khai báo finalkhi thực hiện (nhưng không bị ép buộc cho trận chung kết).
ADTC

"Đây thực sự không phải là một câu trả lời chính xác cho câu hỏi" Bạn nói đúng, tôi không biết tôi đang nghĩ gì ... chắc là vài giờ đầu tháng Bảy hay gì đó. :)
ADTC

2

Tôi tin rằng nó có thể là một chi tiết thừa, vì nó có phải là chi tiết thực hiện hay không.

(Sắp xếp giống như các phương thức / thành viên khai báo trong giao diện là công khai.)

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.