Tại sao tất cả các trường trong một giao diện hoàn toàn là tĩnh và cuối cùng?


100

Tôi chỉ đang cố gắng hiểu tại sao tất cả các trường được xác định trong Giao diện là ngầm định staticfinal. Ý tưởng giữ các trường staticcó ý nghĩa đối với tôi vì bạn không thể có các đối tượng của một giao diện nhưng tại sao chúng lại như vậy final(ngầm hiểu)?

Bất kỳ ai biết lý do tại sao các nhà thiết kế Java đã đi với việc tạo các trường trong một giao diện staticfinal?


Đối với một lưu ý cho bản thân tôi: Nó tĩnh vì các trường của giao diện sẽ không trở thành một phần của đối tượng triển khai nó.
Mưa

Câu trả lời:


126

Một giao diện không thể có hành vi hoặc trạng thái vì nó chỉ nhằm chỉ định một hợp đồng tương tác, không có chi tiết triển khai. 'Không có hành vi nào' được thực thi bằng cách không cho phép các thân phương thức / hàm tạo hoặc các khối khởi tạo phiên bản / tĩnh. 'Không có trạng thái' được thực thi bằng cách chỉ cho phép các trường cuối cùng tĩnh. Do đó, lớp có thể có một trạng thái (trạng thái tĩnh), nhưng trạng thái thể hiện không được suy ra bởi giao diện.

BTW: Một hằng số trong Java được xác định bởi một trường cuối cùng tĩnh (và theo quy ước, tên sử dụng UPPER_CASE_AND_UNDERSCORES).


54
Không nhất thiết phải đúng khi các trường cuối cùng là hằng số; điều đó chỉ được đảm bảo cho các kiểu nguyên thủy. Nói chung, từ khóa cuối cùng chỉ có nghĩa là vị trí bộ nhớ sẽ không thay đổi.
Pops

8
Tôi không nói trường cuối cùng là hằng số, chỉ là hằng số là trường cuối cùng. Lưu ý rằng nó được phép đặt một trường cuối cùng tĩnh không nguyên thủy trong một giao diện. Mặc dù nội dung của trường đó có thể thay đổi, nhưng tham chiếu đến nó là không đổi.
Adriaan Koster

1
@AdriaanKoster Bạn đã nói chính xác rằng trường cuối cùng là hằng số: Không có trạng thái nào được thực thi bằng cách chỉ cho phép các hằng số. - câu này ngụ ý rằng tất cả các trường cuối cùng là không đổi. Bạn có thể cố gắng tranh luận thêm về những từ bạn đã sử dụng, nhưng rõ ràng tuyên bố của bạn đang gây hiểu nhầm.
Tomáš Zato - Phục hồi Monica

2
Đó hẳn là trí tuệ đang suy yếu của tôi nhưng sau sáu năm nhìn vào câu trả lời này, đây là câu trả lời cho điểm cao nhất của tôi, tôi vẫn không hiểu những lời nhận xét. Vui lòng đề xuất một từ ngữ khác bởi vì tôi không thể thấy bất cứ điều gì sai.
Adriaan Koster

Các nhà thiết kế java có thể có ý định tạo một giao diện không trạng thái, nhưng họ đã thất bại vì một trường cá thể có thể là một lớp có thể sửa đổi. Thay vì thừa nhận rằng họ đã thất bại, họ chọn buộc các trường thể static finalhiện gần giống với thực (thực sự là C / C ++) constnhư bạn có thể nhận được trong java. Thật không may, điều này là ngầm và có thể dẫn đến sự nhầm lẫn cho những người không phải là chuyên gia. (Tôi chỉ nhận ra rằng họ là staticvì tôi quan sát thấy hành vi không mong đợi Tôi đã học được rằng họ đang có. finalChỉ từ câu trả lời này.)
không-một-người dùng

27

Lý do để được final

Bất kỳ triển khai nào cũng có thể thay đổi giá trị của các trường nếu chúng không được xác định là cuối cùng. Sau đó, họ sẽ trở thành một phần của việc thực hiện. Giao diện là một đặc tả thuần túy mà không có bất kỳ triển khai nào.

Lý do để được static

Nếu chúng là tĩnh, thì chúng thuộc về giao diện, không phải đối tượng, cũng không phải kiểu thời gian chạy của đối tượng.


18

Có một số điểm được đánh dấu ở đây:

Chỉ vì các trường trong giao diện là cuối cùng tĩnh không có nghĩa là chúng phải là hằng số thời gian biên dịch, hoặc thậm chí là bất biến. Bạn có thể xác định ví dụ:

interface I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("hello");
}

(Hãy lưu ý rằng thực hiện điều này bên trong định nghĩa chú thích có thể gây nhầm lẫn cho javac , liên quan đến thực tế là phần trên thực sự biên dịch thành trình khởi tạo tĩnh.)

Ngoài ra, lý do cho sự hạn chế này là phong cách hơn là kỹ thuật và rất nhiều người muốn thấy nó được thoải mái .


9

Các trường phải tĩnh vì chúng không thể trừu tượng (như các phương thức có thể). Bởi vì chúng không thể trừu tượng, những người triển khai sẽ không thể cung cấp một cách hợp lý việc triển khai các trường khác nhau.

Các trường phải là cuối cùng, tôi nghĩ, vì các trường có thể được truy cập bởi nhiều người triển khai khác nhau cho phép chúng có thể thay đổi có thể có vấn đề (như đồng bộ hóa). Cũng để tránh nó được thực hiện lại (ẩn).

Chỉ là suy nghĩ của tôi.


NawMan, lời giải thích của bạn về "Các tấm chắn phải tĩnh ..." không có ý nghĩa nhiều. Nhưng bạn đã rất đúng khi nói "Các lĩnh vực phải là cuối cùng ..."
peakit

1
Tôi không nghĩ anh ấy đúng về lý do tại sao các lĩnh vực phải là cuối cùng. Việc cho phép những người triển khai khác nhau thay đổi một trường không phải là vấn đề, vì nếu không thì việc kế thừa sẽ có vấn đề. Các trường phải là trường cuối cùng, như Adriaan đã nói, bởi vì một giao diện, và nên là không có trạng thái. Một giao diện có trạng thái về cơ bản phải là một lớp trừu tượng.
Axelle Ziegler

Nếu bạn có public statictrường không được như vậy final, findbugs sẽ phàn nàn (đúng như vậy!).
Tom Hawtin - tackline

2

Tôi coi yêu cầu các trường phải là cuối cùng là quá hạn chế và là một sai lầm của các nhà thiết kế ngôn ngữ Java. Đôi khi, ví dụ như xử lý cây, khi bạn cần thiết lập các hằng số trong việc triển khai được yêu cầu để thực hiện các hoạt động trên một đối tượng của kiểu giao diện. Việc chọn một đường dẫn mã trên lớp thực thi là một k bùn. Cách giải quyết mà tôi sử dụng là xác định một chức năng giao diện và triển khai nó bằng cách trả về một ký tự:

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

Tuy nhiên, sẽ đơn giản hơn, rõ ràng hơn và ít bị sai lệch hơn khi sử dụng cú pháp này:

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}

Bạn dường như phàn nàn nhiều hơn về các trường tĩnh hơn là cuối cùng.
Daniel Yankowsky

0

Đặc điểm kỹ thuật, hợp đồng ... Lệnh máy để truy cập trường sử dụng địa chỉ đối tượng cộng với bù trường. Vì các lớp có thể triển khai nhiều giao diện, không có cách nào để làm cho trường giao diện không phải cuối cùng có cùng độ lệch trong tất cả các lớp mở rộng giao diện này. Do đó cơ chế khác nhau để truy cập trường phải được thực hiện: hai truy cập bộ nhớ (lấy độ lệch trường, lấy giá trị trường) thay vì một cộng với duy trì loại bảng trường ảo (tương tự của bảng phương thức ảo). Đoán rằng họ không muốn làm phức tạp jvm cho chức năng có thể dễ dàng mô phỏng thông qua những thứ (phương thức) hiện có.

Trong scala, chúng ta có thể có các trường trong giao diện, mặc dù bên trong chúng được triển khai như tôi đã giải thích ở trên (dưới dạng các phương thức).


-1

static:

Bất kỳ thứ gì (biến hoặc phương thức) statictrong Java đều có thể được gọi dưới dạng Classname.variablenamehoặc Classname.methodnamehoặc trực tiếp. Không bắt buộc chỉ gọi nó bằng cách sử dụng tên đối tượng.

Trong giao diện, các đối tượng không thể được khai báo và staticcó thể gọi các biến chỉ thông qua tên lớp mà không cần tên đối tượng.

final:

Nó giúp duy trì một giá trị không đổi cho một biến vì nó không thể bị ghi đè trong các lớp con của nó.

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.