Java Enum return Int


76

Tôi đang gặp sự cố khi khai báo một enum. Những gì tôi đang cố gắng tạo là một enum cho 'DownloadType', trong đó có 3 loại tải xuống (AUDIO, VIDEO, AUDIO_AND_VIDEO).

Tôi đã triển khai mã như sau:

private enum DownloadType {
    AUDIO(0), VIDEO(1), AUDIO_AND_VIDEO(2);
    private final int value;

    private DownloadType(int value) {
        this.value = value;
    }
}

Điều này hoạt động tốt nếu sau đó tôi sử dụng nó như thế này:

DownloadType.AUDIO_AND_VIDEO.value;

Tuy nhiên, tôi muốn nó để tôi không phải yêu cầu 'giá trị'. Tôi có thể nhầm, nhưng đây là cách một số lớp hoạt động trong Java, chẳng hạn như Phông chữ, chẳng hạn để đặt kiểu phông chữ, bạn sử dụng:

Font.PLAIN

Trả về giá trị int, chúng tôi không sử dụng:

Font.PLAIN.value

1
Bạn cũng có thể chỉ cần sử dụng DownloadType.AUDIO_AND_VIDEO trừ khi bạn cần giá trị, tôi có thiếu thứ gì không?
kosa

@Nambari Nếu tôi System.out.println (DownloadType.AUDIO_AND_VIDEO), nó trả về "AUDIO_AND_VIDEO" có vẻ thuộc loại 'DownloadType', không phải int.
Cristian

3
Tôi nghĩ bạn đang nhầm lẫn mục đích của enums. Tại sao bạn cũng cần số nguyên?
Jivings 9/12/12

Bởi vì tôi đang nghĩ nếu sau đó tôi muốn lấy loại mà tôi có thể sử dụng 'if (downloadType == DownloadType.AUDIO) {}', điều đó có đúng không?
Cristian

1
Đó là toString()phương thức được gọi khi bạn in đối tượng của mình. Ngoài ra, PLAIN là một hằng số trong Fontlớp, không phải là một enum.
Andrew Logvinov

Câu trả lời:


102

Font.PLAINkhông một enum. Nó chỉ là một int. Nếu bạn cần lấy giá trị ra khỏi enum, bạn không thể tránh gọi một phương thức hoặc sử dụng a .value, bởi vì enum thực sự là các đối tượng thuộc kiểu riêng của nó, không phải là nguyên thủy.

Nếu bạn thực sự chỉ cần một int, bạn đã phải chấp nhận rằng kiểu an toàn bị mất người dùng có thể vượt qua các giá trị không hợp lệ để API của bạn, bạn có thể xác định những hằng số như intthêm:

public final class DownloadType {
    public static final int AUDIO = 0;
    public static final int VIDEO = 1;
    public static final int AUDIO_AND_VIDEO = 2;

    // If you have only static members and want to simulate a static
    // class in Java, then you can make the constructor private.
    private DownloadType() {}
}

Nhân tiện, valuetrường này thực sự dư thừa vì cũng có một .ordinal()phương thức, vì vậy bạn có thể định nghĩa enumnhư sau:

enum DownloadType { AUDIO, VIDEO, AUDIO_AND_VIDEO }

và nhận "giá trị" bằng cách sử dụng

DownloadType.AUDIO_AND_VIDEO.ordinal()

Chỉnh sửa : Đã sửa mã .. static classkhông được phép trong Java. Xem câu trả lời SO này với giải thích và chi tiết về cách xác định các lớp tĩnh trong Java.


Cảm ơn vì đã làm rõ, điều này đang có ý nghĩa. Thay vì tạo một enum, tôi sẽ tạo một DownloadType công khai {private static final int AUDIO = 0; } ... Đây có phải là Lớp bên trong không? Cảm ơn câu trả lời của bạn.
Cristian

@Cristian: Nó chủ yếu phụ thuộc vào cách bạn muốn truy cập nó.
kennytm 9/12/12

Cám ơn câu trả lời của bạn, được chính xác những gì tôi đang tìm kiếm - chờ đợi 3 phút để chấp nhận
Cristian

Ý bạn là public static final int AUDIO = 0;. Theo như tôi biết constkhông phải là một từ khóa Java hợp lệ.
Benjamin

2
thứ tự có thể dẫn đến hệ thống kém ổn định hơn
hychou

59

Nếu bạn cần lấy giá trị int, chỉ cần có một getter cho giá trị trong ENUM của bạn:

private enum DownloadType {
    AUDIO(1), VIDEO(2), AUDIO_AND_VIDEO(3);
    private final int value;

    private DownloadType(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

public static void main(String[] args) {
    System.out.println(DownloadType.AUDIO.getValue());           //returns 1
    System.out.println(DownloadType.VIDEO.getValue());           //returns 2
    System.out.println(DownloadType.AUDIO_AND_VIDEO.getValue()); //returns 3
}

Hoặc bạn có thể đơn giản sử dụng ordinal()phương thức, phương thức này sẽ trả về vị trí của hằng số enum trong enum.

private enum DownloadType {
    AUDIO(0), VIDEO(1), AUDIO_AND_VIDEO(2);
    //rest of the code
}

System.out.println(DownloadType.AUDIO.ordinal());            //returns 0
System.out.println(DownloadType.VIDEO.ordinal());            //returns 1
System.out.println(DownloadType.AUDIO_AND_VIDEO.ordinal()); //returns 2

3
Tại sao bạn cần thêm phương thức khi bạn chỉ có thể gọi .value và đã có một phương thức ordinal () được cung cấp để lấy số nguyên.
kosa

@Nambari umm, dint bí quyết enum có thứ tự .. cách ngu ngốc của tôi: P
PermGenError

@GanGnaMStYleOverFlowErroR Cảm ơn câu trả lời, nhưng tôi thực sự đang tìm cách tránh gọi .value, hãy để một mình tạo một phương thức khác và gọi getValue () :)
Cristian

@GanGnaMStYleOverFlowErroR: Đúng vậy, tôi có thể đã làm rõ điều đó trong nhận xét của mình.
kosa

@Nambari no problomo, cảm ơn vì đã cho tôi biết về thứ tự () :)
PermGenError

16

Trước tiên, bạn nên tự hỏi mình câu hỏi sau: Bạn có thực sự cần một int?

Mục đích của enums là có một tập hợp các mục (hằng số), có ý nghĩa trong mã mà không cần dựa vào giá trị bên ngoài (như int). Enums trong Java có thể được sử dụng như một đối số trên các trạng thái switch và chúng có thể được so sánh một cách an toàn bằng cách sử dụng toán tử bình đẳng "==" (trong số những người khác).

Đề xuất 1 (không cần số nguyên):

Thường thì không cần số nguyên đằng sau nó, sau đó chỉ cần sử dụng điều này:

private enum DownloadType{
    AUDIO, VIDEO, AUDIO_AND_VIDEO
}

Sử dụng:

DownloadType downloadType = MyObj.getDownloadType();
if (downloadType == DownloadType.AUDIO) {
    //...
}
//or
switch (downloadType) {
  case AUDIO:  //...
          break;
  case VIDEO: //...
          break;
  case AUDIO_AND_VIDEO: //...
          break;
}

Đề xuất 2 (int cần thiết):

Tuy nhiên, đôi khi có thể hữu ích khi chuyển đổi một enum thành một int (ví dụ: nếu một API bên ngoài mong đợi các giá trị int). Trong trường hợp này, tôi khuyên bạn nên đánh dấu các phương thức là phương thức chuyển đổi bằng cách sử dụng toXxx()Kiểu. Để ghi đè in toString().

private enum DownloadType {
    AUDIO(2), VIDEO(5), AUDIO_AND_VIDEO(11);
    private final int code;

    private DownloadType(int code) {
        this.code = code;
    }

    public int toInt() {
        return code;
    }

    public String toString() {
        //only override toString, if the returned value has a meaning for the
        //human viewing this value 
        return String.valueOf(code);
    }
}

System.out.println(DownloadType.AUDIO.toInt());           //returns 2
System.out.println(DownloadType.AUDIO);                   //returns 2 via `toString/code`
System.out.println(DownloadType.AUDIO.ordinal());         //returns 0
System.out.println(DownloadType.AUDIO.name());            //returns AUDIO
System.out.println(DownloadType.VIDEO.toInt());           //returns 5
System.out.println(DownloadType.VIDEO.ordinal());         //returns 1
System.out.println(DownloadType.AUDIO_AND_VIDEO.toInt()); //returns 11

Tóm lược

  • Không sử dụng Integer cùng với enum nếu bạn không cần thiết.
  • Đừng dựa vào việc sử dụng ordinal()để lấy một số nguyên của một enum, vì giá trị này có thể thay đổi, nếu bạn thay đổi thứ tự (ví dụ bằng cách chèn một giá trị). Nếu bạn đang cân nhắc sử dụng ordinal(), có thể tốt hơn là sử dụng đề xuất 1.
  • Thông thường, không sử dụng hằng số int thay vì enum (như trong câu trả lời được chấp nhận), vì bạn sẽ mất an toàn kiểu.

1 để chỉ sự toString()mặc dù int trở thành một String và tôi sẽ không sử dụng nó vì :) rằng
António Almeida

... sau đó sử dụng ordinal(). Nhưng toInt()theo tôi thì tốt hơn
yonojoy

10

Đơn giản chỉ cần gọi ordinal()phương thức trên một giá trị enum, để lấy số tương ứng của nó. Không cần khai báo một thuộc tính bổ sung với giá trị của nó, mỗi giá trị được liệt kê sẽ nhận số riêng của nó theo mặc định, được gán bắt đầu từ 0, tăng dần cho mỗi giá trị theo cùng thứ tự mà chúng đã được khai báo.

Bạn không nên phụ thuộc vào intgiá trị của một enum, chỉ phụ thuộc vào giá trị thực của nó. Enums trong Java là một loại quái vật khác và không giống như enums trong C, nơi bạn phụ thuộc vào mã số nguyên của chúng.

Về ví dụ bạn cung cấp trong câu hỏi, Font.PLAINhoạt động vì đó chỉ là một hằng số nguyên của lớp Phông chữ. Nếu bạn thực sự cần một mã số (có thể thay đổi), thì an enumkhông phải là công cụ phù hợp cho công việc, tốt hơn là hãy bám vào các hằng số.


1
Tôi biết về ordinal (), nhưng nếu sau đó tôi muốn thay đổi hoặc chỉ định một thứ tự khác trong tương lai, điều này sẽ gây ra sự cố. Tôi muốn chỉ định giá trị int
Cristian

1
@Cristian bạn không nên phụ thuộc vào giá trị int của một enum, chỉ phụ thuộc vào giá trị thực của nó. Enums trong Java không giống như enums trong C, nơi bạn phụ thuộc vào mã số nguyên của chúng.
Óscar López

@Cristian và liên quan đến ví dụ bạn cung cấp trong câu hỏi Font.PLAINhoạt động vì đó chỉ là một hằng số nguyên của Fontlớp. Nếu bạn thực sự cần một mã số (có thể thay đổi), thì an enumkhông phải là công cụ phù hợp cho công việc, tốt hơn hết hãy bám vào các hằng số.
Óscar López

5

Bạn có thể thử mã này.

private enum DownloadType {
    AUDIO , VIDEO , AUDIO_AND_VIDEO ;

}

Bạn có thể sử dụng liệt kê này là như thế này: DownloadType.AUDIO.ordinal(). Hy vọng đoạn mã này sẽ giúp ích cho bạn.


3

Nếu bạn đang nối enum với một chuỗi, bạn có thể ghi đè phương thức toString để trả về int:

public String toString() {
    return value + "";
}

Sau đó, bạn chỉ cần sử dụng:

String something = "foo" + DownloadType.AUDIO;

và phương thức toString () sẽ được gọi.


Lưu ý rằng việc sử dụng toString () theo lập trình thường được coi là thực hành kém - nó chỉ dành cho mắt người, tuy nhiên đây là cách duy nhất để đạt được những gì bạn đang yêu cầu.


3

Bạn có muốn mã này không?

public static enum FieldIndex {
    HDB_TRX_ID,     //TRX ID
    HDB_SYS_ID      //SYSTEM ID
}

public String print(ArrayList<String> itemName){
    return itemName.get(FieldIndex.HDB_TRX_ID.ordinal());
}

2

Theo tôi, phiên bản đáng đọc nhất

public enum PIN_PULL_RESISTANCE {
    PULL_UP {
        @Override
        public int getValue() {
            return 1;
        }
    },
    PULL_DOWN {
        @Override
        public int getValue() {
            return 0;
        }
    };

    public abstract int getValue();
}
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.