Khi nào bạn sử dụng chú thích @Override của Java và tại sao?


498

Các thực tiễn tốt nhất để sử dụng @Overridechú thích của Java là gì và tại sao?

Có vẻ như sẽ là quá mức cần thiết để đánh dấu mọi phương thức được ghi đè bằng @Overridechú thích. Có những tình huống lập trình nhất định kêu gọi sử dụng @Overridevà những tình huống khác không bao giờ nên sử dụng @Override?

Câu trả lời:


515

Sử dụng nó mỗi khi bạn ghi đè một phương thức cho hai lợi ích. Làm điều đó để bạn có thể tận dụng kiểm tra trình biên dịch để đảm bảo rằng bạn thực sự đang ghi đè một phương thức khi bạn nghĩ rằng bạn đang có. Theo cách này, nếu bạn mắc một lỗi phổ biến là viết sai tên phương thức hoặc không khớp chính xác các tham số, bạn sẽ được cảnh báo rằng phương thức của bạn không thực sự ghi đè như bạn nghĩ. Thứ hai, nó làm cho mã của bạn dễ hiểu hơn vì nó rõ ràng hơn khi các phương thức được ghi đè.

Ngoài ra, trong Java 1.6, bạn có thể sử dụng nó để đánh dấu khi một phương thức thực hiện một giao diện cho cùng các lợi ích. Tôi nghĩ sẽ tốt hơn nếu có một chú thích riêng (như @Implements), nhưng tốt hơn là không có gì.


4
Cùng một dòng là "dễ hiểu hơn", các IDE sẽ phát hiện ra chú thích @Override và gắn cờ trực quan phương thức ghi đè trong trình chỉnh sửa.
Bob Cross

47
Một số IDE sẽ gắn cờ một phương thức ghi đè bị thiếu chú thích @Override.
Jay R.

20
Lợi ích khác là nếu lớp cha thay đổi, trình biên dịch sẽ đảm bảo rằng các lớp con cũng đã được cập nhật.
David

4
@Jay R.: Đúng. Như một vấn đề thực tế, ví dụ, Eclipse thậm chí có thể tự động thêm @Override nếu nó bị thiếu.
sleske

32
Trong trường hợp bất kỳ ai khác đến đây vì sự thay đổi rõ ràng không có giấy tờ từ 1,5 đến 1,6 đối với @Overrides trên các phương thức đến từ các giao diện, bug.sun.com/bugdatabase/view_orms.do?bug_id=5008260 dường như là lỗi tương ứng. (Cảm ơn vì đã chỉ ra, Dave L.!)
Henrik Heimbuerger

110

Tôi nghĩ rằng nó hữu ích nhất như một lời nhắc thời gian biên dịch rằng ý định của phương thức là ghi đè một phương thức cha. Ví dụ:

protected boolean displaySensitiveInformation() {
  return false;
}

Bạn sẽ thường thấy một cái gì đó giống như phương thức trên ghi đè một phương thức trong lớp cơ sở. Đây là một chi tiết triển khai quan trọng của lớp này - chúng tôi không muốn thông tin nhạy cảm được hiển thị.

Giả sử phương thức này được thay đổi trong lớp cha thành

protected boolean displaySensitiveInformation(Context context) {
  return true;
}

Thay đổi này sẽ không gây ra bất kỳ lỗi thời gian biên dịch hoặc cảnh báo nào - nhưng nó thay đổi hoàn toàn hành vi dự định của lớp con.

Để trả lời câu hỏi của bạn: bạn nên sử dụng chú thích @Override nếu việc thiếu một phương thức có cùng chữ ký trong siêu lớp là dấu hiệu của lỗi.


46

Có nhiều câu trả lời hay ở đây, vì vậy hãy để tôi đưa ra một cách khác để xem xét nó ...

Không có quá mức cần thiết khi bạn đang mã hóa. Bạn không mất gì khi nhập @override, nhưng khoản tiết kiệm có thể rất lớn nếu bạn viết sai tên phương thức hoặc chữ ký hơi sai.

Hãy suy nghĩ về nó theo cách này: Trong thời gian bạn điều hướng ở đây và gõ bài đăng này, bạn đã sử dụng khá nhiều thời gian hơn là bạn sẽ dành thời gian gõ @override cho đến hết đời; nhưng một lỗi nó ngăn chặn có thể giúp bạn tiết kiệm hàng giờ.

Java làm tất cả những gì có thể để đảm bảo bạn không mắc lỗi nào trong thời gian chỉnh sửa / biên dịch, đây là cách gần như miễn phí để giải quyết toàn bộ một loại lỗi không thể ngăn chặn được bằng bất kỳ cách nào khác ngoài kiểm tra toàn diện.

Bạn có thể đưa ra một cơ chế tốt hơn trong Java để đảm bảo rằng khi người dùng có ý định ghi đè một phương thức, anh ta thực sự đã làm gì?

Một hiệu ứng thú vị khác là nếu bạn không cung cấp chú thích, nó sẽ cảnh báo bạn vào thời gian biên dịch rằng bạn vô tình áp đảo phương thức cha mẹ - một điều có thể có ý nghĩa nếu bạn không có ý định thực hiện.


3
"Không có quá mức cần thiết khi bạn đang mã hóa." Tôi đồng ý với điều này, đó là lý do tại sao tôi thấy lang động rất sai (mặc dù 100% công việc được trả tiền của tôi hiện đang ở trong ruby).
Dan Rosenstark

4
+1: Có thể, tôi đã có 10 lỗi do lỗi ghi đè - thời gian cần thiết để tìm bất kỳ lỗi nào trong số chúng sẽ dễ dàng vượt quá thời gian để nhập @Override trên mỗi phương thức ghi đè của tôi. Bên cạnh đó, nếu @Override là một số gánh nặng, có lẽ bạn đang sử dụng thừa kế.
Lawrence Dol

7
Một nhược điểm rất thực tế là bạn làm cho mã khó đọc hơn bằng cách xả rác bằng ốc. Có lẽ đây là một lỗi của IDE của tôi, nhưng tôi đã tự mình trải nghiệm điều này.
đối xử tốt với các mod của bạn vào

9
@phyzome Nếu bạn thấy "Ốc sên" cồng kềnh, bạn không sử dụng BẤT CỨ Ý kiến ​​nào. Chúng chỉ nên là một dòng trên tiêu đề phương thức của bạn, nó phải lớn bằng phương thức của bạn trong hầu hết các trường hợp (một vài dòng) để cung cấp văn bản di chuột và javadocs phong nha. Tôi đoán tôi đang nói rằng vấn đề không phải là Ốc, đó là thói quen đọc sách của bạn. Có phải tất cả các dấu ngoặc trong mã cũng làm phiền bạn không?
Bill K

4
Vâng, có quá mức trong mã hóa: khi bạn viết bình luận chỉ vẹt những gì mã rõ ràng làm.
Kiến

22

Tôi luôn luôn sử dụng thẻ. Đó là một lá cờ thời gian biên dịch đơn giản để bắt những lỗi nhỏ mà tôi có thể mắc phải.

Nó sẽ bắt những thứ như tostring()thay vìtoString()

Những điều nhỏ giúp trong các dự án lớn.


18

Sử dụng @Overridechú thích hoạt động như một biện pháp bảo vệ thời gian biên dịch chống lại một lỗi lập trình phổ biến. Nó sẽ đưa ra một lỗi biên dịch nếu bạn có chú thích trên một phương thức mà bạn không thực sự ghi đè lên phương thức siêu lớp.

Trường hợp phổ biến nhất mà điều này hữu ích là khi bạn thay đổi một phương thức trong lớp cơ sở để có một danh sách tham số khác. Một phương thức trong một lớp con được sử dụng để ghi đè phương thức siêu lớp sẽ không còn làm như vậy do chữ ký phương thức đã thay đổi. Điều này đôi khi có thể gây ra hành vi kỳ lạ và bất ngờ, đặc biệt là khi xử lý các cấu trúc thừa kế phức tạp. Các @Overridechú thích bảo vệ chống lại điều này.


Câu trả lời tốt nhất. Ngắn và ngọt. Tôi ước bạn có thể giải thích mặc dù cách "bảo vệ" hoạt động .... không ai giải thích điều này.
djangofan

Thật đơn giản để giải thích. Nếu bạn mắc lỗi (bằng cách thay đổi giao diện, lớp trừu tượng hoặc lớp con, bạn sẽ nhận được cảnh báo (chẳng hạn như trong Eclipse) hoặc lỗi thời gian biên dịch cho bạn biết rằng @Override của bạn không hoạt động. thông báo sẽ phụ thuộc vào những gì đã được thay đổi, nhưng trong Eclipse (ví dụ) rất rõ ràng rằng có một vấn đề: bạn sẽ thấy phần gạch chân ngoằn ngoèo nhỏ màu đỏ đó, và một con trỏ trên văn bản vi phạm sẽ cho bạn biết điều gì sai. Tôi gọi đó là Giá trị Tốt.
Ichiro Furusato

14

Để tận dụng lợi thế từ việc kiểm tra trình biên dịch, bạn phải luôn sử dụng chú thích Ghi đè. Nhưng đừng quên rằng Trình biên dịch Java 1.5 sẽ không cho phép chú thích này khi ghi đè các phương thức giao diện. Bạn chỉ có thể sử dụng nó để ghi đè các phương thức lớp (trừu tượng hoặc không).

Một số IDE, như Eclipse, thậm chí được cấu hình với thời gian chạy Java 1.6 trở lên, chúng vẫn duy trì tuân thủ Java 1.5 và không cho phép sử dụng @override như được mô tả ở trên. Để tránh hành vi đó, bạn phải truy cập: Thuộc tính dự án -> Trình biên dịch Java -> Kiểm tra kích hoạt Cài đặt cụ thể của dự án Cài đặt -> Chọn Mức độ tuân thủ của Trình biên dịch mã hóa = 6.0 hoặc cao hơn.

Tôi thích sử dụng chú thích này mỗi khi tôi ghi đè một phương thức một cách độc lập, nếu cơ sở là một giao diện hoặc lớp.

Điều này giúp bạn tránh một số lỗi điển hình, như khi bạn nghĩ rằng bạn đang ghi đè một trình xử lý sự kiện và sau đó bạn thấy không có gì xảy ra. Hãy tưởng tượng bạn muốn thêm một trình lắng nghe sự kiện vào một số thành phần UI:

someUIComponent.addMouseListener(new MouseAdapter(){
  public void mouseEntered() {
     ...do something...
  }
});

Đoạn mã trên sẽ biên dịch và chạy, nhưng nếu bạn di chuyển con chuột vào bên trong một số thành phần thì hãy thực hiện một cái gì đó mã Code sẽ lưu ý chạy, bởi vì thực sự bạn không ghi đè phương thức cơ sở mouseEntered(MouseEvent ev). Bạn chỉ cần tạo một phương thức không tham số mới mouseEntered(). Thay vì mã đó, nếu bạn đã sử dụng @Overridechú thích, bạn đã thấy một lỗi biên dịch và bạn đã không lãng phí thời gian để suy nghĩ tại sao trình xử lý sự kiện của bạn không chạy.


8

@Override khi thực hiện giao diện không nhất quán vì không có thứ gọi là "ghi đè giao diện" trong java.

@Override khi thực hiện giao diện là vô ích vì trong thực tế, nó không gặp phải lỗi nào mà trình biên dịch sẽ không bắt được. Chỉ có một kịch bản được tải rất xa trong đó ghi đè lên người triển khai thực sự làm một việc gì đó: Nếu bạn triển khai một giao diện và các phương thức XÓA giao diện, bạn sẽ được thông báo về thời gian biên dịch rằng bạn nên xóa các triển khai không sử dụng. Lưu ý rằng nếu phiên bản mới của giao diện có các phương thức MỚI hoặc THAY ĐỔI thì rõ ràng bạn sẽ gặp lỗi biên dịch vì dù sao bạn không triển khai công cụ mới.

@Override trên các trình triển khai giao diện không bao giờ được phép trong 1.6 và với nhật thực buồn khi chọn tự động chèn các chú thích làm hành vi mặc định, chúng tôi nhận được rất nhiều tệp nguồn lộn xộn. Khi đọc mã 1.6, bạn không thể thấy từ chú thích @Override nếu một phương thức thực sự ghi đè một phương thức trong siêu lớp hoặc chỉ thực hiện một giao diện.

Sử dụng @Override khi thực sự ghi đè một phương thức trong siêu lớp là tốt.


2
Có nhiều ý kiến ​​khác nhau về điểm đó. Xem stackoverflow.com/questions/212614/ trên .
sleske

8

Tốt nhất nên sử dụng nó cho mọi phương thức nhằm mục đích ghi đè và Java 6+, mọi phương thức nhằm mục đích triển khai giao diện.

Đầu tiên, nó bắt lỗi chính tả như " hashcode()" thay vì " hashCode()" tại thời gian biên dịch. Nó có thể gây khó khăn để gỡ lỗi tại sao kết quả của phương thức của bạn dường như không khớp với mã của bạn khi nguyên nhân thực sự là mã của bạn không bao giờ được gọi.

Ngoài ra, nếu một siêu lớp thay đổi chữ ký phương thức, phần ghi đè của chữ ký cũ hơn có thể là "mồ côi", bị bỏ lại dưới dạng mã chết khó hiểu. Các @Overridechú thích sẽ giúp bạn xác định những trẻ mồ côi để họ có thể được sửa đổi để phù hợp với chữ ký mới.


7

Nếu bạn thấy mình thường xuyên ghi đè các phương thức (không trừu tượng), có lẽ bạn muốn xem qua thiết kế của mình. Nó rất hữu ích khi trình biên dịch sẽ không bắt lỗi. Ví dụ, cố gắng ghi đè initValue () trong ThreadLocal, điều mà tôi đã thực hiện.

Sử dụng @Override khi triển khai các phương thức giao diện (tính năng 1.6+) có vẻ hơi quá mức đối với tôi. Nếu bạn có vô số phương thức, một số phương thức ghi đè và một số phương thức thì có thể lại thiết kế xấu (và trình soạn thảo của bạn có thể sẽ hiển thị phương thức nào nếu bạn không biết).


2
Trên thực tế, nó cũng tốt cho các phương thức giao diện overriden. Nếu tôi ví dụ loại bỏ một phương thức cũ, không dùng nữa khỏi một giao diện, thì nên xóa phương thức đó khỏi tất cả các lớp triển khai - dễ dàng phát hiện ra các phương thức đó nếu chúng sử dụng @override.
Dominik Sandjaja

7

@Override trên các giao diện thực sự hữu ích, bởi vì bạn sẽ nhận được cảnh báo nếu bạn thay đổi giao diện.


7

Một điều nữa là nó làm cho nó rõ ràng hơn khi đọc mã rằng nó đang thay đổi hành vi của lớp cha. Hơn có thể giúp gỡ lỗi.

Ngoài ra, trong cuốn sách hiệu quả Java của Joshua Block (ấn bản 2), mục 36 cung cấp thêm chi tiết về lợi ích của chú thích.


Vâng, thực sự - mục 36 :)
Chris Kimpton

6

Hoàn toàn không có ý nghĩa khi sử dụng @Override khi thực hiện phương thức giao diện. Không có lợi thế nào khi sử dụng nó trong trường hợp đó - trình biên dịch sẽ bắt lỗi của bạn, vì vậy nó chỉ là sự lộn xộn không cần thiết.


6
Sử dụng @Overridetrên một giao diện sẽ buộc bạn phải chú ý khi một phương thức trong giao diện bị xóa.
Alex B

@Alex: Loại bỏ các phương thức trong một giao diện là một thay đổi đột phá, như thêm chúng. Khi một giao diện được xuất bản, nó sẽ bị khóa một cách hiệu quả trừ khi bạn có toàn quyền kiểm soát tất cả các mã sử dụng nó.
Lawrence Dol

6

Bất cứ khi nào một phương thức ghi đè lên một phương thức khác hoặc một phương thức thực hiện chữ ký trong một giao diện.

Các @Overridechú thích đảm bảo với bạn rằng bạn đã làm trong thực tế ghi đè lên một cái gì đó. Nếu không có chú thích, bạn có nguy cơ sai chính tả hoặc khác biệt về loại và số tham số.


1
Bạn chỉ có thể sử dụng nó để đánh dấu việc triển khai giao diện trong Java 1.6
Dave L.

5

Tôi sử dụng nó mọi lúc. Đó là nhiều thông tin mà tôi có thể sử dụng để nhanh chóng tìm ra điều gì đang xảy ra khi tôi xem lại mã trong một năm và tôi đã quên những gì tôi nghĩ lần đầu tiên.


5

Cách thực hành tốt nhất là luôn luôn sử dụng nó (hoặc để IDE điền chúng cho bạn)

Tính hữu dụng của @Override là phát hiện các thay đổi trong các lớp cha chưa được báo cáo xuống thứ bậc. Nếu không có nó, bạn có thể thay đổi chữ ký phương thức và quên thay đổi phần ghi đè của nó, với @Override, trình biên dịch sẽ bắt nó cho bạn.

Đó là loại lưới an toàn luôn luôn tốt để có.


1
Vì vậy, nếu bạn thay đổi phương thức cha và việc bạn không sử dụng @Override trong phương thức của lớp con, thì trình biên dịch sẽ nói bất cứ điều gì hay giữ im lặng? Việc sử dụng "Ghi đè" sẽ cung cấp cho bạn thêm thông tin và nếu có thì sao?
djangofan

5

Tôi sử dụng nó ở khắp mọi nơi. Về chủ đề nỗ lực đánh dấu các phương thức, tôi đã để Eclipse làm điều đó cho tôi vì vậy, đó không phải là nỗ lực bổ sung.

Tôi tôn giáo về tái cấu trúc liên tục .... vì vậy, tôi sẽ sử dụng mọi thứ nhỏ nhặt để làm cho nó diễn ra suôn sẻ hơn.


5
  • Chỉ được sử dụng trên khai báo phương pháp.
  • Chỉ ra rằng khai báo phương thức chú thích ghi đè một khai báo trong siêu kiểu.

Nếu được sử dụng một cách nhất quán, nó sẽ bảo vệ bạn khỏi một lớp lớn các lỗi bất chính.

Sử dụng chú thích @Override để tránh các lỗi này: (Phát hiện lỗi trong đoạn mã sau :)

public class Bigram {
    private final char first;
    private final char second;
    public Bigram(char first, char second) {
        this.first  = first;
        this.second = second;
    }
    public boolean equals(Bigram b) {
        return b.first == first && b.second == second;
    }
    public int hashCode() {
        return 31 * first + second;
    }

    public static void main(String[] args) {
        Set<Bigram> s = new HashSet<Bigram>();
        for (int i = 0; i < 10; i++)
            for (char ch = 'a'; ch <= 'z'; ch++)
                s.add(new Bigram(ch, ch));
        System.out.println(s.size());
    }
}

nguồn: Java hiệu quả


Tôi không biết các quy tắc ưu tiên toán tử là gì trong Java, nhưng phương thức bằng của bạn đang hét BUUUUUUUUUUUUG! Tôi sẽ viết (b.first == first) && (b.second == second), ngay cả khi &&có quyền ưu tiên thấp hơn ==.
pyon

Bạn có biết rằng liên kết của bạn hiển thị thông báo 'bạn phải đăng ký' bao gồm phần hữu ích của trang đó không?
Quảng trường Adriano Varoli

@Adriano: Xin lỗi anh bạn !! Bất lực !! Khi tôi viết 'câu trả lời', nó đã có sẵn. Đừng lo lắng..buy mua cuốn sách. Thật đáng để có nó !!
jai

5
Phương thức equals không ghi đè: Bản gốc Object::equalsboolean equals(Object), trong khi phần ghi đè equalsboolean equals(Bigram), có chữ ký phương thức khác, không ghi đè. Thêm @Override vào equalssẽ phát hiện ra lỗi này.
Ming-Tang

3

Hãy cẩn thận khi bạn sử dụng Ghi đè, vì sau đó bạn không thể thực hiện kỹ sư đảo ngược trong starUML; làm cho uml đầu tiên.


2

Dường như sự khôn ngoan ở đây đang thay đổi. Hôm nay tôi đã cài đặt IntelliJ IDEA 9 và nhận thấy rằng " kiểm tra @Override bị thiếu " của nó giờ đây không chỉ bắt các phương thức trừu tượng mà còn triển khai các phương thức giao diện. Trong cơ sở mã của chủ nhân và trong các dự án của riêng tôi, từ lâu tôi đã có thói quen chỉ sử dụng @Override cho các phương thức trừu tượng được triển khai trước đây. Tuy nhiên, suy nghĩ lại về thói quen, giá trị của việc sử dụng các chú thích trong cả hai trường hợp trở nên rõ ràng. Mặc dù dài dòng hơn, nhưng nó bảo vệ chống lại vấn đề của lớp cơ sở mong manh (không nghiêm trọng như các ví dụ liên quan đến C ++) khi tên phương thức giao diện thay đổi, mồ côi phương thức triển khai trong lớp dẫn xuất.

Tất nhiên, kịch bản này chủ yếu là cường điệu; lớp dẫn xuất sẽ không còn biên dịch nữa, bây giờ thiếu một triển khai phương thức giao diện được đổi tên và ngày nay người ta có thể sẽ sử dụng một hoạt động tái cấu trúc Phương thức đổi tên để giải quyết toàn bộ cơ sở mã.

Do việc kiểm tra của IDEA không thể định cấu hình để bỏ qua các phương thức giao diện đã triển khai, hôm nay tôi sẽ thay đổi cả thói quen xem xét tiêu chí mã nhóm của tôi.


2

Chú thích @Override được sử dụng để giúp kiểm tra xem nhà phát triển có ghi đè phương thức đúng trong lớp cha hoặc giao diện hay không. Khi tên của các phương thức của super thay đổi, trình biên dịch có thể thông báo cho trường hợp đó, chỉ dành cho việc giữ sự thống nhất với siêu lớp và lớp con.

BTW, nếu chúng tôi không công bố chú thích @Override trong lớp con, nhưng chúng tôi ghi đè một số phương thức của siêu, thì hàm có thể hoạt động như một phương thức với @Override. Nhưng phương pháp này không thể thông báo cho nhà phát triển khi phương thức của super đã được thay đổi. Bởi vì nó không biết mục đích của nhà phát triển - ghi đè phương thức siêu hay xác định phương thức mới?

Vì vậy, khi chúng ta muốn ghi đè phương thức đó để sử dụng Đa hình, chúng ta nên thêm @Override bên trên phương thức.


1

Tôi sử dụng nó nhiều nhất có thể để xác định khi nào một phương thức bị ghi đè. Nếu bạn nhìn vào ngôn ngữ lập trình Scala, họ cũng có một từ khóa ghi đè. Tôi thấy nó hữu ích.


0

Nó cho phép bạn (tốt, trình biên dịch) nắm bắt khi bạn sử dụng sai chính tả trên tên phương thức mà bạn đang ghi đè.


0

Chú thích ghi đè được sử dụng để tận dụng trình biên dịch, để kiểm tra xem bạn có thực sự ghi đè một phương thức từ lớp cha hay không. Nó được sử dụng để thông báo nếu bạn mắc bất kỳ lỗi nào như sai chính tả tên phương thức, lỗi không khớp chính xác các tham số


0

tôi nghĩ tốt nhất nên viết mã @override bất cứ khi nào được phép. Nó giúp cho mã hóa. tuy nhiên, cần lưu ý, đối với Helios ecipse, hoặc sdk 5 hoặc 6, chú thích @override cho các phương thức giao diện đã triển khai được cho phép. đối với Galileo, 5 hoặc 6, chú thích @override không được phép.


0

Các chú thích cung cấp dữ liệu meta về mã cho Trình biên dịch và chú thích @Override được sử dụng trong trường hợp thừa kế khi chúng ta ghi đè bất kỳ phương thức nào của lớp cơ sở. Nó chỉ cho trình biên dịch biết rằng bạn đang ghi đè phương thức. Nó có thể tránh được một số loại lỗi phổ biến mà chúng ta có thể làm như không tuân theo chữ ký thích hợp của phương thức hoặc viết sai tên của phương thức, v.v ... Vì vậy, nên sử dụng chú thích @Override.


0

Đối với tôi, @Override đảm bảo với tôi rằng tôi có chữ ký của phương thức đúng. Nếu tôi đặt chú thích và phương thức không được viết đúng chính tả, thì trình biên dịch sẽ phàn nàn cho tôi biết có gì đó không đúng.


0

Đơn giản khi bạn muốn ghi đè một phương thức có trong siêu lớp của mình, hãy sử dụng @Overridechú thích để ghi đè chính xác. Trình biên dịch sẽ cảnh báo bạn nếu bạn không ghi đè chính xác.

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.