Tại sao các biến giao diện tĩnh và cuối cùng theo mặc định?


273

Tại sao các biến giao diện tĩnh và cuối cùng theo mặc định trong Java?


41
Bạn không nên đặt bất kỳ biến nào trong Giao diện.
cherouvim

34
Bởi vì các giao diện xác định các hợp đồng có thể được thực hiện theo nhiều cách khác nhau. Giá trị của một biến là thực hiện.
cherouvim

10
Chúng ta chắc chắn có thể khi chúng ta biết tất cả các lớp thực hiện giao diện có một số biến không đổi (ví dụ tên trường).
Aniket Thakur

Có phải là một ý tưởng tốt để biến một biến trong một lớp thành một thể hiện của giao diện mà lớp thực hiện không? Tôi đã nghe điều này trước đây.
Doug Hauf

Các giao diện trong java tuân theo nguyên tắc ACID, cuối cùng vì sự chuẩn hóa trong C. @cherouvim Loại biến là việc thực hiện, một biến phải được khai báo, có hoặc không có giá trị và định nghĩa của biến là giá trị. Nếu bạn thay đổi giá trị của một biến không được thực hiện lại, thì việc xác định lại nó.
Grim

Câu trả lời:


263

Từ thiết kế giao diện Java FAQ của Philip Shaw:

Các biến giao diện là tĩnh vì các giao diện Java không thể được khởi tạo theo cách riêng của chúng; giá trị của biến phải được gán trong ngữ cảnh tĩnh trong đó không có trường hợp nào tồn tại. Công cụ sửa đổi cuối cùng đảm bảo giá trị được gán cho biến giao diện là hằng số thực không thể được gán lại bởi mã chương trình.

nguồn


39
Lưu ý rằng các lớp trừu tượng không thể được khởi tạo "theo quyền riêng của chúng" và cả các lớp có thể có các biến thể hiện.
macias

18
Giải thích cho staticsửa đổi này là hoàn toàn giả mạo. Các biến cá thể công khai của một lớp là một phần của giao diện của nó và không có lý do nào khiến chúng không được trừu tượng hóa trong Java interface, giống như các phương thức cá thể. Không có vấn đề gì khi Java interfacekhông thể được khởi tạo trực tiếp - bạn vẫn có thể có các thể hiện của các lớp thực hiện interfacevà điều hợp lý là yêu cầu chúng có một biến cá thể công khai nhất định. Về phần final, điều đó không đưa ra một lời giải thích nào cả - nó chỉ mô tả ý finalnghĩa của nó.
pyrocrasty

3
Các trích dẫn ở trên là tốt hơn trong bối cảnh. Lý do nó đưa ra là "các biến giao diện được dự định là các hằng số Java". Các trích dẫn chỉ là chi tiết về lý do tại sao một hằng số như vậy sẽ là tĩnh và cuối cùng. Điều đó đúng, nhưng câu hỏi thực sự là: tại sao các biến không được phép là một phần của giao diện thực tế (nghĩa là chỉ định tên và loại thành viên không riêng tư phải xảy ra trong một lớp triển khai). Nếu họ muốn "hằng số giao diện" đặc biệt, họ có thể đã sử dụng cú pháp mới hoặc chỉ quyết định rằng bất kỳ biến nào thực sự được xác định trong giao diện là hằng số giao diện.
pyrocrasty

6
Các giao diện không thể có các biến đối tượng để tránh sự kế thừa nhiều vấn đề trạng thái. Xem docs.oracle.com/javase/tutorial/java/IandI/ ,. Một lớp không thể mở rộng nhiều hơn một lớp vì cùng một lý do.
chối

1
Các phương thức mặc định được giới thiệu như thế nào và chúng có thể hiện, nhưng biến thể hiện không được hỗ trợ ...
M.kazem Akhÿ

41

Vì giao diện không có đối tượng trực tiếp, nên cách duy nhất để truy cập chúng là sử dụng lớp / giao diện và đó là lý do tại sao nếu biến giao diện tồn tại, thì nó phải tĩnh nếu không nó có thể truy cập được ở bên ngoài. Bây giờ vì nó là tĩnh, nó chỉ có thể giữ một giá trị và bất kỳ lớp nào thực hiện nó có thể thay đổi nó và do đó tất cả sẽ là mớ hỗn độn.

Do đó, nếu có một biến giao diện, nó sẽ hoàn toàn tĩnh, cuối cùng và rõ ràng là công khai !!!


Tất nhiên một biến cá thể sẽ có thể truy cập được nếu nó được cho phép trong Java interface. Một lớp sẽ thực hiện giao diện, khai báo biến thể hiện (theo yêu cầu của giao diện). Hàm tạo của nó (hoặc phương thức khác) đặt biến thể hiện. Khi một thể hiện của lớp được khởi tạo, bạn sẽ có thể truy cập biến thể hiện của nó.
pyrocrasty

Java cho phép các phương thức tĩnh với các cơ thể tồn tại trong một giao diện. Những người có thể truy cập các biến tĩnh. Họ chỉ không thể thay đổi chúng, điều đó có nghĩa là các hàm tĩnh không thể lưu trữ bất kỳ dữ liệu nào
đơn giản hóa

36

công khai : cho khả năng truy cập trên tất cả các lớp, giống như các phương thức có trong giao diện

static : vì giao diện không thể có một đối tượng, interfaceName.variableName có thể được sử dụng để tham chiếu nó hoặc trực tiếp biếnName trong lớp thực hiện nó.

sau cùng : để làm cho chúng hằng. Nếu 2 lớp thực hiện cùng một giao diện và bạn cho cả hai quyền thay đổi giá trị, xung đột sẽ xảy ra trong giá trị hiện tại của var, đó là lý do tại sao chỉ cho phép khởi tạo một lần.

Ngoài ra tất cả các sửa đổi này là ẩn cho một giao diện, bạn không thực sự cần phải chỉ định bất kỳ trong số chúng.


15

( Đây không phải là một câu trả lời triết học mà là một câu trả lời thực tế ). Yêu cầu staticsửa đổi là rõ ràng đã được trả lời bởi những người khác. Về cơ bản, vì các giao diện không thể được khởi tạo, cách duy nhất để truy cập các trường của nó là biến chúng thành một trường lớp - static.

Lý do đằng sau các interfacetrường tự động trở thành final(không đổi) là để ngăn các triển khai khác nhau vô tình thay đổi giá trị của biến giao diện, điều này có thể vô tình ảnh hưởng đến hành vi của các triển khai khác. Hãy tưởng tượng kịch bản bên dưới nơi mà một thuộc interfacetính không finalđược Java rõ ràng trở thành :

public interface Actionable {
    public static boolean isActionable = false;

    public void performAction();
}

public NuclearAction implements Actionable {

    public void performAction() {
        // Code that depends on isActionable variable
        if (isActionable) {
            // Launch nuclear weapon!!!
        }
    }
}

Bây giờ, chỉ cần nghĩ điều gì sẽ xảy ra nếu một lớp khác thực hiện Actionablethay đổi trạng thái của biến giao diện:

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

Nếu các lớp này được tải trong một JVM duy nhất bởi một trình nạp lớp, thì hành vi của NuclearActioncó thể bị ảnh hưởng bởi một lớp khác CleanAction, khi nó performAction()được gọi sauCleanAction được thực thi (trong cùng một luồng hoặc theo cách khác), trong trường hợp này có thể là thảm họa (về mặt ngữ nghĩa là vậy).

Vì chúng ta không biết làm thế nào mỗi triển khai của một interfacesẽ sử dụng các biến này, nên chúng phải hoàn toàn final.


9

Bởi vì bất cứ điều gì khác là một phần của việc triển khai và các giao diện không thể chứa bất kỳ triển khai nào.


1
Vậy thì lý do cuối cùng là gì.
Jothi

7
Để chỉ ra rằng nó là một hằng số. Java không có từ khóa const. tĩnh cuối cùng là cách bạn khai báo hằng.
Amir Afghani

5
Kể từ Java 8, chúng có thể chứa một triển khai, nhưng chúng tôi khuyên bạn không nên sử dụng nó nếu bạn không cần khả năng tương thích ngược. :)
codepleb

6
public interface A{
    int x=65;
}
public interface B{
    int x=66;
}
public class D implements A,B {
    public static void main(String[] a){
        System.out.println(x); // which x?
    }
}

Đây là giải pháp.

System.out.println(A.x); // done

Tôi nghĩ đó là một lý do tại sao biến giao diện là tĩnh.

Đừng khai báo các biến trong Giao diện.


3
Trên thực tế, nếu không có đặc tả "Axe", nó thậm chí sẽ không biên dịch ", do đó, thực sự an toàn khi sử dụng các biến (mà hoàn toàn là công khai tĩnh cuối cùng) trong các giao diện.
Marco

Tôi không đồng ý với câu trả lời, vì @Marco nói rằng nó thậm chí sẽ không được biên dịch. Tôi đã không tìm thấy bất kỳ nhược điểm nào khác cho đến nay, có lẽ chỉ là bạn không thấy được viết static finaltrước biến thực sự là tĩnh và cuối cùng.
Micer

5

tĩnh - bởi vì Giao diện không thể có bất kỳ trường hợp nào. và cuối cùng - bởi vì chúng ta không cần phải thay đổi nó.


15
"chúng tôi không cần" == "chúng tôi không được phép", không trộn lẫn các ý nghĩa.
peterh - Phục hồi lại

3

bởi vì:

Static : vì chúng ta không thể có các đối tượng của giao diện, vì vậy chúng ta nên tránh sử dụng các biến thành viên cấp đối tượng và nên sử dụng các biến cấp độ lớp tức là tĩnh.

Final : để chúng ta không nên có các giá trị mơ hồ cho các biến (Vấn đề kim cương - Đa kế thừa).

Và theo giao diện tài liệu là một hợp đồng và không phải là một thực hiện.

tham khảo: Câu trả lời của Abhishek Jain về quora


2

Java không cho phép các biến trừu tượng và / hoặc các định nghĩa hàm tạo trong các giao diện. Giải pháp: Chỉ cần treo một lớp trừu tượng giữa giao diện của bạn và triển khai của bạn, nó chỉ mở rộng lớp trừu tượng như vậy:

 public interface IMyClass {

     void methodA();
     String methodB();
     Integer methodC();

 }

 public abstract class myAbstractClass implements IMyClass {
     protected String varA, varB;

     //Constructor
     myAbstractClass(String varA, String varB) {
         this.varA = varA;
         this.varB = VarB;
     }

     //Implement (some) interface methods here or leave them for the concrete class
     protected void methodA() {
         //Do something
     }

     //Add additional methods here which must be implemented in the concrete class
     protected abstract Long methodD();

     //Write some completely new methods which can be used by all subclasses
     protected Float methodE() {
         return 42.0;
     }

 }

 public class myConcreteClass extends myAbstractClass {

     //Constructor must now be implemented!
     myClass(String varA, String varB) {
         super(varA, varB);
     }

     //All non-private variables from the abstract class are available here
     //All methods not implemented in the abstract class must be implemented here

 }

Bạn cũng có thể sử dụng một lớp trừu tượng mà không có bất kỳ giao diện nào nếu bạn CHẮC CHẮN rằng bạn không muốn triển khai nó cùng với các giao diện khác sau này. Xin lưu ý rằng bạn không thể tạo một thể hiện của một lớp trừu tượng mà bạn PHẢI mở rộng nó trước.

(Từ khóa "được bảo vệ" có nghĩa là chỉ các lớp mở rộng mới có thể truy cập các phương thức và biến này.)

gián điệp



1

Giao diện: Dịch vụ yêu cầu hệ thống.

Trong giao diện, biến được mặc định gán bởi công cụ sửa đổi truy cập công khai, tĩnh, cuối cùng . Bởi vì :

công khai: Đôi khi giao diện có thể được đặt trong một số gói khác. Vì vậy, nó cần phải truy cập vào biến từ bất cứ nơi nào trong dự án.

static: Vì lớp không đầy đủ như vậy không thể tạo đối tượng. Vì vậy, trong dự án chúng ta cần truy cập vào biến không có đối tượng để có thể truy cập với sự trợ giúp củainterface_filename.variable_name

cuối cùng: Giả sử một giao diện thực hiện bởi nhiều lớp và tất cả các lớp cố gắng truy cập và cập nhật biến giao diện. Vì vậy, nó dẫn đến sự không nhất quán của việc thay đổi dữ liệu và ảnh hưởng đến mọi lớp khác. Vì vậy, nó cần phải khai báo sửa đổi truy cập với cuối cùng.


0

Trong Java, giao diện không cho phép bạn khai báo bất kỳ biến đối tượng nào. Sử dụng một biến được khai báo trong giao diện làm biến thể hiện sẽ trả về lỗi thời gian biên dịch.

Bạn có thể khai báo một biến không đổi, sử dụng biến static finalkhác với biến thể hiện.


Điều này hoàn toàn sai. Trình biên dịch sẽ không phàn nàn trừ khi bạn đặt nó ở chế độ riêng tư hoặc được bảo vệ. Dưới mui xe, như những người khác đã đề cập, họ được chuyển đổi thành trận chung kết tĩnh công khai. Và tôi đoán nó khá rõ ràng tại sao. Bởi vì giao diện có nghĩa là để ra lệnh cho hành vi, không phải trạng thái.
Mikayil Abdullayev

0

Giao diện có thể được thực hiện bởi bất kỳ lớp nào và nếu giá trị đó bị thay đổi bởi một trong các lớp triển khai thì sẽ có sự hiểu lầm cho các lớp thực hiện khác. Giao diện về cơ bản là một tham chiếu để kết hợp hai thực thể corelated nhưng khác nhau. Vì lý do đó, biến khai báo bên trong giao diện sẽ hoàn toàn là cuối cùng và cũng là tĩnh vì giao diện không thể được khởi tạo.


0

Hãy nghĩ về một ứng dụng web nơi bạn có giao diện được xác định và các lớp khác thực hiện nó. Vì bạn không thể tạo một thể hiện của giao diện để truy cập các biến bạn cần có một từ khóa tĩnh. Vì tĩnh của nó, bất kỳ thay đổi nào trong giá trị sẽ phản ánh đến các trường hợp khác đã triển khai nó. Vì vậy, để ngăn chặn nó, chúng tôi xác định chúng là cuối cùng.


0

Chỉ cần thử trong Eclipse, biến trong giao diện được mặc định là cuối cùng, vì vậy bạn không thể thay đổi nó. So với lớp cha, các biến chắc chắn có thể thay đổi. Tại sao? Theo quan điểm của tôi, biến trong lớp là một thuộc tính sẽ được thừa hưởng bởi trẻ em và trẻ em có thể thay đổi nó theo nhu cầu thực tế của chúng. Ngược lại, giao diện chỉ xác định hành vi, không thuộc tính. Lý do duy nhất để đặt các biến trong giao diện là sử dụng chúng như các hằng số liên quan đến giao diện đó. Mặc dù, đây không phải là một thực hành tốt theo đoạn trích sau:

"Đặt các hằng số trong một giao diện là một kỹ thuật phổ biến trong thời kỳ đầu của Java, nhưng bây giờ nhiều người coi đó là việc sử dụng giao diện một cách khó chịu, vì các giao diện nên xử lý các dịch vụ được cung cấp bởi một đối tượng, chứ không phải dữ liệu của nó. bởi một lớp thường là một chi tiết triển khai, nhưng việc đặt chúng trong một giao diện sẽ thúc đẩy chúng đến API công khai của lớp. "

Tôi cũng đã thử đặt tĩnh hoặc không làm cho sự khác biệt nào cả. Mã như sau:

public interface Addable {
    static int count = 6;

    public int add(int i);

}

public class Impl implements Addable {

    @Override
    public int add(int i) {
        return i+count;
    }
}

public class Test {

    public static void main(String... args) {
        Impl impl = new Impl();

        System.out.println(impl.add(4));
    }
}
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.