So sánh các thành viên enum Java: == hoặc bằng ()?


1736

Tôi biết rằng các enum Java được biên dịch thành các lớp với các hàm tạo riêng và một nhóm các thành viên tĩnh công khai. Khi so sánh hai thành viên của một enum nhất định, tôi đã luôn sử dụng .equals(), vd

public useEnums(SomeEnum a)
{
    if(a.equals(SomeEnum.SOME_ENUM_VALUE))
    {
        ...
    }
    ...
}

Tuy nhiên, tôi chỉ bắt gặp một số mã sử dụng toán tử bằng ==thay vì .equals ():

public useEnums2(SomeEnum a)
{
    if(a == SomeEnum.SOME_ENUM_VALUE)
    {
        ...
    }
    ...
}

Toán tử nào tôi nên sử dụng?


7
Tôi vừa vấp phải một câu hỏi rất giống nhau: stackoverflow.com/questions/533922/ trên
Matt Ball

39
Tôi ngạc nhiên rằng trong tất cả các câu trả lời (đặc biệt là câu trả lời từ đa gen giải thích chi tiết tại sao == hoạt động) rằng một lợi ích lớn khác của == đã không được đề cập: nó làm cho rõ ràng cách thức hoạt động của enums (như một tập hợp đơn lẻ cố định các đối tượng). Bằng với nó, nó khiến người ta nghĩ rằng bằng cách nào đó có thể có nhiều trường hợp của cùng một enum 'thay thế' nổi xung quanh.
Stuart Rossiter

6
Giữ cho nó đơn giản. "==" dễ đọc hơn và nó hoạt động vì enums là singleton theo mặc định. Ref
Lokesh

Câu trả lời:


1578

Cả hai đều đúng kỹ thuật. Nếu bạn nhìn vào mã nguồn .equals(), nó chỉ đơn giản là trì hoãn ==.

Tôi sử dụng ==, tuy nhiên, vì điều đó sẽ không an toàn.


64
Cá nhân, tôi không thích 'an toàn null' được đề cập như một lý do để sử dụng ==.
Nivas

258
@Nivas: tại sao không? Bạn có muốn lo lắng về thứ tự các đối số của mình (chỉ áp dụng để so sánh các hằng số từ bên trái, như trong câu trả lời của Pascal) không? Bạn có muốn luôn luôn kiểm tra rằng một giá trị không phải là null trước khi nhập .equals()nó? Tôi biết tôi không.
Matt Ball

86
Hãy nhớ rằng khi đọc mã của bạn, "==" có thể xuất hiện không chính xác với người đọc cho đến khi anh ta / cô ta tắt và nhìn vào nguồn cho loại liên quan, sau đó thấy đó là một enum. Theo nghĩa đó, việc đọc ".equals ()" sẽ ít gây mất tập trung hơn.
Kevin Bourrillion

60
@Kevin - nếu bạn không sử dụng IDE cho phép bạn xem các loại trực tiếp khi xem nguồn, bạn đang tự lừa dối mình - không phải là vấn đề với IDE phù hợp.
MetroidFan2002

63
Đôi khi mã được tái cấu trúc và có thể một enum được thay thế bởi một lớp, tại thời điểm đó == không còn được đảm bảo là chính xác, trong khi các đẳng thức tiếp tục hoạt động trơn tru. Vì lý do này, bằng nhau rõ ràng là một lựa chọn tốt hơn. Nếu bạn muốn an toàn null (vì bạn làm việc trên cơ sở mã không được viết để giảm thiểu việc sử dụng null), thì có ObjectUtils hoặc Guava's Object # bằng nhau (hoặc bạn có thể tự cuộn). Tôi thậm chí sẽ không đề cập đến từ "hiệu suất" vì sợ rằng ai đó tát tôi một cách chính đáng với một cuốn sách Donald Knuth.
laszlok

1113

Có thể ==được sử dụng trên enum?

Có: enums có các điều khiển cá thể chặt chẽ cho phép bạn sử dụng ==để so sánh các thể hiện. Đây là sự đảm bảo được cung cấp bởi đặc tả ngôn ngữ (nhấn mạnh bởi tôi):

JLS 8,9

Một loại enum không có trường hợp nào khác ngoài các trường hợp được xác định bởi hằng số enum của nó.

Đó là một lỗi thời gian biên dịch để cố gắng khởi tạo một cách rõ ràng một kiểu enum. Các final clonephương pháp trong EnumĐảm bảo rằng enumhằng không bao giờ có thể được nhân bản vô tính, và điều trị đặc biệt bởi cơ chế này để thỏa mãn serialization rằng trường hợp trùng lặp không bao giờ được tạo ra như là một kết quả của deserialization. Phản xạ tức thời của các loại enum bị cấm. Cùng với nhau, bốn điều này đảm bảo rằng không có trường hợp nào thuộc enumloại tồn tại ngoài những trường hợp được xác định bởi các enumhằng số.

Do chỉ có một thể hiện của mỗi enumhằng số, nên cho phép sử dụng ==toán tử thay cho equalsphương thức khi so sánh hai tham chiếu đối tượng nếu biết rằng ít nhất một trong số chúng tham chiếu đến enumhằng số . ( equalsPhương thức trong Enumlà một finalphương thức chỉ đơn thuần gọi ra super.equalsđối số của nó và trả về kết quả, do đó thực hiện so sánh danh tính.)

Bảo đảm này đủ mạnh để Josh Bloch khuyến nghị, rằng nếu bạn khăng khăng sử dụng mẫu đơn, cách tốt nhất để thực hiện là sử dụng một phần tử duy nhất enum(xem: Phiên bản Java 2 hiệu quả, Mục 3: Thi hành thuộc tính singleton với nhà xây dựng riêng hoặc một loại enum , cũng an toàn chủ đề trong Singleton )


Sự khác biệt giữa ==và là equalsgì?

Xin nhắc lại, cần phải nói rằng nói chung, ==KHÔNG phải là sự thay thế khả thi equals. Tuy nhiên, khi đó (chẳng hạn như với enum), có hai sự khác biệt quan trọng cần xem xét:

== không bao giờ ném NullPointerException

enum Color { BLACK, WHITE };

Color nothing = null;
if (nothing == Color.BLACK);      // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException

== có thể kiểm tra tính tương thích tại thời điểm biên dịch

enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };

if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine
if (Color.BLACK == Chiral.LEFT);      // DOESN'T COMPILE!!! Incompatible types!

Có nên ==dùng khi áp dụng?

Bloch đặc biệt đề cập rằng các lớp bất biến có quyền kiểm soát thích hợp đối với các thể hiện của họ có thể đảm bảo cho khách hàng của họ ==có thể sử dụng được. enumđược đề cập cụ thể để minh họa.

Mục 1: Xem xét các phương thức nhà máy tĩnh thay vì các nhà xây dựng

[...] nó cho phép một lớp bất biến đưa ra sự đảm bảo rằng không có hai trường hợp bằng nhau tồn tại: a.equals(b)if và only if a==b. Nếu một lớp thực hiện đảm bảo này, thì các máy khách của nó có thể sử dụng ==toán tử thay vì equals(Object)phương thức, điều này có thể dẫn đến hiệu suất được cải thiện. Các loại Enum cung cấp đảm bảo này.

Để tóm tắt, các đối số để sử dụng ==trên enumlà:

  • Nó hoạt động.
  • Nó nhanh hơn.
  • Nó an toàn hơn vào thời gian chạy.
  • Nó an toàn hơn vào thời gian biên dịch.

27
Câu trả lời hay nhưng ... 1. Nó hoạt động : đã đồng ý 2. nhanh hơn : chứng minh điều đó cho enum :) 3. An toàn hơn vào thời gian chạy : Color nothing = null;là IMHO một lỗi và nên được sửa, enum của bạn có hai giá trị, không phải ba ( xem bình luận của Tom Hawtin) 4. An toàn hơn vào thời gian biên dịch : OK, nhưng equalsvẫn sẽ quay lại false. Cuối cùng, tôi không mua nó, tôi thích equals()sự dễ đọc hơn (xem bình luận của Kevin).
Pascal Thivent

201
Đó là một dấu đen đối với Java mà một số người cho rằng foo.equals(bar)dễ đọc hơnfoo == bar
Bennett McElwee

19
Nó hoạt động: Cho đến khi bạn cần thay thế một enum bằng một lớp như là một phần của tái cấu trúc. Chúc may mắn tìm thấy tất cả các mã bằng cách sử dụng == mà phá vỡ. Nó nhanh hơn: Ngay cả khi đúng (có thể nghi ngờ), có trích dẫn Knuth về tối ưu hóa sớm. An toàn hơn trong thời gian chạy: "An toàn" không phải là từ đầu tiên nảy ra trong đầu nếu việc sử dụng == là điều duy nhất ngăn cách bạn với NullPulumException. An toàn hơn tại thời gian biên dịch: Không thực sự. Nó có thể bảo vệ bạn khỏi sai lầm khá cơ bản khi so sánh các loại sai, nhưng một lần nữa, nếu đó là cách lập trình viên của bạn ngu ngốc, "an toàn" là điều bạn không nên làm.
laszlok

35
"nếu đó là cách các lập trình viên của bạn câm," an toàn "là điều bạn không làm." - Tôi không đồng ý với trích dẫn này. Đây là loại kiểm tra tất cả về: ngăn ngừa các lỗi "ngu ngốc" trong thời gian biên dịch, do đó ngay cả trước khi mã được chạy. Ngay cả những người thông minh cũng làm những sai lầm ngớ ngẩn, một số đảm bảo tốt hơn so với những lời hứa.
ymajoros

7
@laszlok: chắc chắn, nhưng nếu mọi thứ có thể thất bại, họ sẽ làm. Có một hàng rào cho một số sai lầm ngớ ngẩn luôn là một điều tốt. Có rất nhiều chỗ để sáng tạo cho các lỗi ít tầm thường hơn, hãy để trình biên dịch xử lý lỗi này trước khi bạn thử chạy mã của mình.
ymajoros

88

Sử dụng ==để so sánh hai giá trị enum hoạt động, bởi vì chỉ có một đối tượng cho mỗi hằng số enum.

Bên cạnh đó, thực sự không cần sử dụng ==để viết mã null-safe, nếu bạn viết equals()như thế này:

public useEnums(final SomeEnum a) {
    if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
        
    }
    
}

Đây là một cách thực hành tốt nhất được gọi là So sánh các hằng số từ bên trái mà bạn chắc chắn nên tuân theo.


9
Tôi làm điều này khi nhập .equals()các giá trị chuỗi, nhưng tôi vẫn nghĩ rằng đó là một cách ngu ngốc để viết mã không an toàn. Tôi muốn có một toán tử (hoặc một phương thức, nhưng tôi biết rằng [đối tượng null] .equals sẽ không bao giờ là null an toàn trong Java vì cách toán tử dấu chấm hoạt động) luôn an toàn, bất kể theo thứ tự nó được sử dụng. Về mặt ngữ nghĩa, toán tử "bằng" phải luôn luôn đi lại.
Matt Ball

2
Chà, vì Java không có toán tử điều hướng an toàn của Groovy ( ?.), tôi sẽ tiếp tục sử dụng thực tiễn này khi so sánh với các hằng số và, TBH, tôi không thấy nó nhảm nhí, có lẽ chỉ kém "tự nhiên".
Pascal Thivent

32
Một nullenum thường là một lỗi. Bạn đã có bảng liệt kê tất cả các giá trị có thể, và đây là một giá trị khác!
Tom Hawtin - tackline

8
Ngoại trừ các giá trị được chú thích rõ ràng là @Nullable, tôi xem xét So sánh các hằng số từ bên trái một phản mẫu vì nó lan truyền sự mơ hồ về giá trị nào có thể hoặc không thể là null. Các loại Enum hầu như không bao giờ nên @Nullable, vì vậy giá trị null sẽ là lỗi lập trình; trong trường hợp như vậy, bạn ném NPE càng sớm thì càng có nhiều khả năng bạn sẽ thấy lỗi lập trình của mình khi bạn cho phép nó không có giá trị. Vì vậy, "thực hành tốt nhất ... mà bạn chắc chắn nên tuân theo" là hoàn toàn sai khi nói đến các loại enum.
Tobias

24
So sánh các hằng số từ bên trái một cách thực hành tốt nhất như tiếng Anh theo phong cách Yoda tốt nhất.
maaartinus

58

Như những người khác đã nói, cả hai ==.equals()làm việc trong hầu hết các trường hợp. Sự chắc chắn về thời gian biên dịch mà bạn không so sánh các loại Đối tượng hoàn toàn khác nhau mà những người khác đã chỉ ra là hợp lệ và có lợi, tuy nhiên loại lỗi đặc biệt so sánh các đối tượng của hai loại thời gian biên dịch khác nhau cũng sẽ được FindBugs tìm thấy (và có lẽ bởi Eclipse / IntelliJ biên dịch kiểm tra thời gian), vì vậy trình biên dịch Java tìm thấy nó không tăng thêm độ an toàn.

Tuy nhiên:

  1. Thực tế là ==không bao giờ ném NPE trong tâm trí của tôi là một bất lợi của ==. Hầu như không cần phải có enumloại null, vì bất kỳ trạng thái bổ sung nào bạn muốn thể hiện thông qua nullchỉ có thể được thêm vào enumnhư một ví dụ bổ sung. Nếu điều đó là bất ngờ null, tôi thà có một NPE hơn là ==âm thầm đánh giá thành sai. Vì vậy, tôi không đồng ý với ý kiến an toàn hơn trong thời gian chạy ; tốt hơn hết là tập thói quen không bao giờ để enumgiá trị @Nullable.
  2. Lập luận rằng ==nhanh hơn cũng là không có thật. Trong hầu hết các trường hợp, bạn sẽ gọi .equals()vào một biến có thời gian biên dịch kiểu là lớp enum, và trong những trường hợp trình biên dịch có thể biết rằng đây là giống như ==(vì một enum's equals()phương pháp không thể ghi đè) và có thể tối ưu hóa các chức năng gọi xa. Tôi không chắc trình biên dịch hiện có làm điều này không, nhưng nếu không, và hóa ra đó là một vấn đề về hiệu năng trong Java nói chung, thì tôi muốn sửa trình biên dịch hơn là có 100.000 lập trình viên Java thay đổi phong cách lập trình cho phù hợp một đặc điểm hiệu suất của phiên bản trình biên dịch cụ thể.
  3. enumslà các đối tượng. Đối với tất cả các loại Đối tượng khác, so sánh tiêu chuẩn là .equals()không ==. Tôi nghĩ đó là nguy hiểm để làm một ngoại lệ cho enumsbởi vì bạn có thể kết thúc vô tình so sánh các đối tượng với ==thay equals(), đặc biệt là nếu bạn cấu trúc lại một enumvào một lớp học không enum. Trong trường hợp tái cấu trúc như vậy, điểm hoạt động từ phía trên là sai. Để thuyết phục bản thân rằng việc sử dụng ==là chính xác, bạn cần kiểm tra xem giá trị trong câu hỏi là một enumhoặc nguyên thủy; nếu nó không phải là một enumlớp, nó sẽ sai nhưng dễ bị bỏ lỡ vì mã vẫn sẽ được biên dịch. Trường hợp duy nhất khi sử dụng.equals()sẽ là sai nếu các giá trị trong câu hỏi là nguyên thủy; trong trường hợp đó, mã sẽ không biên dịch nên khó bỏ sót hơn nhiều. Do đó, .equals()dễ dàng hơn nhiều để xác định là chính xác và an toàn hơn đối với các phép tái cấu trúc trong tương lai.

Tôi thực sự nghĩ rằng ngôn ngữ Java nên đã xác định == trên các Đối tượng để gọi .equals () trên giá trị bên trái và giới thiệu một toán tử riêng cho nhận dạng đối tượng, nhưng đó không phải là cách Java được định nghĩa.

Tóm lại, tôi vẫn nghĩ rằng các đối số có lợi cho việc sử dụng .equals()cho enumcác loại.


4
Chà, về điểm 3, tôi có thể sử dụng enumlàm switchmục tiêu nên chúng hơi đặc biệt. Strings cũng có một chút đặc biệt
RèmDog

Cú pháp cho các câu lệnh chuyển đổi không chứa == hay .equals () vì vậy tôi không thấy quan điểm của bạn là gì. Quan điểm của tôi 3.) là về cách dễ dàng xác minh mã cho người đọc. Ngữ nghĩa công bằng của câu lệnh chuyển đổi là chính xác miễn là câu lệnh chuyển đổi biên dịch.
Tobias

17

Tôi thích sử dụng ==thay vì equals:

Một lý do khác, ngoài những lý do khác đã được thảo luận ở đây, là bạn có thể giới thiệu một lỗi mà không nhận ra. Giả sử bạn có enum này hoàn toàn giống nhau nhưng trong các nhịp riêng biệt (nó không phổ biến, nhưng nó có thể xảy ra):

Enum đầu tiên :

package first.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

Enum thứ hai:

package second.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

Sau đó, giả sử bạn sử dụng các số bằng như tiếp theo item.category, first.pckg.Categorynhưng bạn nhập enum thứ hai ( second.pckg.Category) thay vì đầu tiên mà không nhận ra nó:

import second.pckg.Category;
...

Category.JAZZ.equals(item.getCategory())

Vì vậy, bạn sẽ nhận được allways falsedo là một enum khác nhau mặc dù bạn mong đợi vì sự thật item.getCategory()JAZZ. Và nó có thể là một chút khó khăn để xem.

Vì vậy, nếu bạn sử dụng toán tử thay vào đó, ==bạn sẽ gặp lỗi biên dịch:

toán tử == không thể được áp dụng cho "second.pckg.C Category", "first.pckg.C Category"

import second.pckg.Category; 
...

Category.JAZZ == item.getCategory() 

Điểm rất tốt mà bạn đề cập. Vì vậy, những gì tôi sẽ làm là vỗ tay myenum.value () và sau đó thực hiện == comparaison cho an toàn NPE.
Java

14

Dưới đây là một bài kiểm tra thời gian thô để so sánh hai:

import java.util.Date;

public class EnumCompareSpeedTest {

    static enum TestEnum {ONE, TWO, THREE }

    public static void main(String [] args) {

        Date before = new Date();
        int c = 0;

        for(int y=0;y<5;++y) {
            for(int x=0;x<Integer.MAX_VALUE;++x) {
                if(TestEnum.ONE.equals(TestEnum.TWO)) {++c;}
                if(TestEnum.ONE == TestEnum.TWO){++c;}              
            }
        }

        System.out.println(new Date().getTime() - before.getTime());
    }   

}

Nhận xét các IF một lần. Dưới đây là hai so sánh từ trên trong mã byte được phân tách:

 21  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 24  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 27  invokevirtual EnumCompareSpeedTest$TestEnum.equals(java.lang.Object) : boolean [28]
 30  ifeq 36

 36  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 39  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 42  if_acmpne 48

Đầu tiên (bằng) thực hiện một cuộc gọi ảo và kiểm tra boolean trả về từ ngăn xếp. Thứ hai (==) so sánh các địa chỉ đối tượng trực tiếp từ ngăn xếp. Trong trường hợp đầu tiên có nhiều hoạt động hơn.

Tôi đã chạy thử nghiệm này nhiều lần với cả hai IF một lần. "==" nhanh hơn một chút.


Tôi nghi ngờ rằng dự đoán nhánh của trình biên dịch có thể làm cho thử nghiệm này không hợp lệ. Một trình biên dịch thông minh sẽ nhận ra rằng cả hai câu lệnh if sẽ luôn luôn đánh giá thành sai và do đó tránh thực hiện nhiều so sánh. Một trình biên dịch thực sự thông minh thậm chí có thể nhận ra rằng các giá trị trong các vòng lặp y và x sẽ không ảnh hưởng đến kết quả và tối ưu hóa toàn bộ ...
Darrel Hoffman

Nó có thể, nhưng nó chắc chắn không. Tôi hiển thị mã byte do trình biên dịch thực tế tạo ra trong câu trả lời của tôi.
ChrisCantrell 04/07/2015

bạn đang bối rối :-) Dự đoán chi nhánh hoạt động vào thời gian chạy nên mã byte khác nhau không liên quan lắm. Tuy nhiên, trong trường hợp này dự đoán nhánh sẽ giúp cả hai trường hợp như nhau.
vidstige

7
Ai quan tâm? Trừ khi bạn đang so sánh enum hàng ngàn lần trong một vòng lặp trong một trò chơi video thì thêm nano giây là vô nghĩa.
dùng949300

Mã byte khá không liên quan đến hiệu suất trừ khi bạn buộc chế độ diễn giải. Viết một tiêu chuẩn JMH để thấy rằng hiệu suất là hoàn toàn giống nhau.
maaartinus


7

tl; dr

Một lựa chọn khác là Objects.equalsphương pháp tiện ích.

Objects.equals( thisEnum , thatEnum )

Objects.equals cho an toàn

bằng toán tử == thay vì .equals ()

Toán tử nào tôi nên sử dụng?

Tùy chọn thứ ba là equalsphương thức tĩnh được tìm thấy trên Objectslớp tiện ích được thêm vào Java 7 trở lên.

Thí dụ

Đây là một ví dụ sử dụng Monthenum.

boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ;  // Returns `false`.

Những lợi ích

Tôi tìm thấy một vài lợi ích cho phương pháp này:

  • Không an toàn
  • Nhỏ gọn, dễ đọc

Làm thế nào nó hoạt động

Logic được sử dụng là Objects.equalsgì?

Xem cho chính mình, từ mã nguồn Java 10 của OpenJDK :

return (a == b) || (a != null && a.equals(b));

6

Sử dụng bất cứ thứ gì khác ngoài ==việc so sánh hằng số enum là vô nghĩa. Nó giống như so sánh classcác đối tượng vớiequals - đừng làm điều đó!

Tuy nhiên, có một lỗi khó chịu (BugId 6277781 ) trong Sun JDK 6u10 và trước đó có thể thú vị vì lý do lịch sử. Lỗi này đã ngăn chặn việc sử dụng đúng cách ==trên các enumialized, mặc dù điều này được cho là phần nào của một trường hợp góc.


4

Enums là các lớp trả về một thể hiện (như singletons) cho mỗi hằng số liệt kê được khai báo bởi public static final field(không thay đổi) để ==toán tử có thể được sử dụng để kiểm tra đẳng thức của chúng thay vì sử dụng equals()phương thức


1

Lý do enums hoạt động dễ dàng với == là vì mỗi trường hợp được xác định cũng là một singleton. Vì vậy, so sánh danh tính bằng cách sử dụng == sẽ luôn hoạt động.

Nhưng sử dụng == vì nó hoạt động với enum có nghĩa là tất cả mã của bạn được kết hợp chặt chẽ với việc sử dụng enum đó.

Ví dụ: Enums có thể thực hiện một giao diện. Giả sử bạn hiện đang sử dụng một enum thực hiện Interface1. Nếu sau này, ai đó thay đổi nó hoặc giới thiệu một lớp Impl1 mới như là một triển khai của cùng một giao diện. Sau đó, nếu bạn bắt đầu sử dụng các phiên bản của Impl1, bạn sẽ có rất nhiều mã để thay đổi và kiểm tra vì việc sử dụng == trước đó.

Do đó, tốt nhất là làm theo những gì được coi là một thực hành tốt trừ khi có bất kỳ lợi ích chính đáng nào.


Câu trả lời tốt đẹp, nhưng đã được đề cập ở đây .
shmosel

Ừm. Tại thời điểm đó, câu hỏi sẽ là về việc bạn sử dụng == hoặc bằng trên một giao diện. Cộng với tất cả các loại câu hỏi về việc liệu có thực sự hợp lý để thay thế việc thực hiện một loại không thay đổi bằng cách thực hiện có thể thay đổi hay không. Và có lẽ là khôn ngoan để tìm ra thực hành tốt là gì trước khi bạn lo lắng về lợi ích chính đáng. (imho == là thực hành tốt hơn).
Robin Davies

1

Một trong những quy tắc của Sonar là Enum values should be compared with "==". Những lý do như sau:

Việc kiểm tra sự bằng nhau của một giá trị enum equals()là hoàn toàn hợp lệ vì enum là một Đối tượng và mọi nhà phát triển Java đều ==không nên sử dụng để so sánh nội dung của một Đối tượng. Đồng thời, sử dụng ==trên enums:

  • cung cấp sự so sánh dự kiến ​​tương tự (nội dung) như equals()

  • an toàn hơn null equals()

  • cung cấp kiểm tra thời gian biên dịch (tĩnh) thay vì kiểm tra thời gian chạy

Vì những lý do này, việc sử dụng ==nên được ưu tiên equals().

Cuối cùng nhưng không kém phần quan trọng, các ==enums trên được cho là dễ đọc hơn (ít dài dòng hơn) equals().


0

Tóm lại, cả hai đều có ưu và nhược điểm.

Một mặt, nó có lợi thế để sử dụng ==, như được mô tả trong các câu trả lời khác.

Mặt khác, nếu bạn vì bất kỳ lý do nào, hãy thay thế enum bằng một cách tiếp cận khác (trường hợp lớp bình thường), đã sử dụng ==bạn cắn. (BTDT.)


-1

Tôi muốn bổ sung câu trả lời đa gen:

Cá nhân tôi thích bằng (). Nhưng nó kiểm tra khả năng tương thích loại. Mà tôi nghĩ là một hạn chế quan trọng.

Để kiểm tra tính tương thích loại tại thời gian biên dịch, hãy khai báo và sử dụng hàm tùy chỉnh trong enum của bạn.

public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable

Với điều này, bạn có tất cả lợi thế của cả hai giải pháp: bảo vệ NPE, dễ đọc mã và kiểm tra tính tương thích loại tại thời gian biên dịch.

Tôi cũng khuyên bạn nên thêm một giá trị UNDEFINED cho enum.


4
Tại sao giải pháp này tốt hơn ==? Với việc ==bạn nhận được bảo vệ NPE, mã dễ đọc và biên dịch kiểm tra khả năng tương thích loại thời gian và bạn có được tất cả những thứ đó mà không cần viết bất kỳ phương thức giống như tùy chỉnh nào.
Matt Ball

1
Một UNDEFINEDgiá trị có lẽ là một ý tưởng tốt. Tất nhiên, trong Java 8, bạn sẽ sử dụng Optionalthay thế.
Tomas
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.