Cách tốt nhất để tạo enum của chuỗi?


364

Cách tốt nhất để có một enumloại đại diện cho một chuỗi các chuỗi là gì?

Tôi đã thử điều này:

enum Strings{
   STRING_ONE("ONE"), STRING_TWO("TWO")
}

Làm thế nào tôi có thể sử dụng chúng như là Strings?

Câu trả lời:


605

Tôi không biết bạn muốn làm gì, nhưng đây là cách tôi thực sự dịch mã ví dụ của bạn ....

package test;

/**
 * @author The Elite Gentleman
 *
 */
public enum Strings {
    STRING_ONE("ONE"),
    STRING_TWO("TWO")
    ;

    private final String text;

    /**
     * @param text
     */
    Strings(final String text) {
        this.text = text;
    }

    /* (non-Javadoc)
     * @see java.lang.Enum#toString()
     */
    @Override
    public String toString() {
        return text;
    }
}

Ngoài ra, bạn có thể tạo một phương thức getter cho text.

Bây giờ bạn có thể làm Strings.STRING_ONE.toString();


3
Tôi không biết nếu nó là một yêu cầu biên dịch, nhưng private String textnên là cuối cùng.
Jonathan

7
@ Tomás Narros Có, bạn vẫn có thể gán cho nó trong hàm tạo, miễn là bạn không cung cấp cho nó một giá trị khi bạn khai báo nó cuối cùng.
Jonathan

28
@ Quý ông ưu tú Sẽ thật tệ nếu giá trị của hằng số enum thay đổi trong thời gian chạy, vì vậy ngay cả khi không bắt buộc, finalsẽ là tốt nhất.
Jonathan

8
Đừng quên rằng Enums không thể được xây dựng newnhư là nhà xây dựng private. Về cơ bản, việc tạo đối tượng bị cấm và finalkhông thực sự cần thiết trong trường hợp này.
Buhake Sindi

6
@BuhakeSindi: đó là sự thật, nhưng vô tình người ta có thể có xu hướng đặt setText(String)enum và điều đó có thể giải phóng địa ngục :) finalloại tài liệu mà bạn nghĩ rằng đó là một hằng số với sự hỗ trợ của trình biên dịch. Nếu bạn sử dụng Stringhằng số, bạn sẽ không khai báo nó public static String, phải không?
TWiStErRob

104

Giá trị chuỗi tùy chỉnh cho Enum

từ http://javahowto.blogspot.com/2006/10/custom-opes-values-for-enum.html

Giá trị chuỗi mặc định cho java enum là mệnh giá của nó hoặc tên thành phần. Tuy nhiên, bạn có thể tùy chỉnh giá trị chuỗi bằng cách ghi đè phương thức toString (). Ví dụ,

public enum MyType {
  ONE {
      public String toString() {
          return "this is one";
      }
  },

  TWO {
      public String toString() {
          return "this is two";
      }
  }
}

Chạy mã kiểm tra sau sẽ tạo ra điều này:

public class EnumTest {
  public static void main(String[] args) {
      System.out.println(MyType.ONE);
      System.out.println(MyType.TWO);
  }
}


this is one
this is two

16
Đây không phải là một cách hiệu quả để làm điều này. Điều này tạo ra một lớp tùy chỉnh mới cho mọi giá trị trong bảng liệt kê. Trong ví dụ trên, bạn sẽ thấy phần sau trong binthư mục: EnumTest $ MyType. Class EnumTest $ MyType $ 1. class EnumTest $ MyType $ 2. class sẽ tăng nhanh thực sự . Tốt nhất để làm điều đó như câu trả lời mong đợi, bằng cách chuyển các giá trị cho hàm tạo enum. Tôi thực sự không đồng ý với việc ghi đè toString(); Tôi tin rằng tốt hơn là sử dụng một getter rõ ràng, chẳng hạn như việc ghi getKey()đè toString()có thể gây bất ngờ bởi một người dùng enum khác.
Matt Quigley

hoàn toàn đồng ý với @MattQuigley. Làm như vậy khuyến khích người dùng sử dụng toString cho những thứ không nên sử dụng. Nếu bạn cần một nhãn, bạn muốn thêm một thuộc tính nhãn
Sebastien Lorber

Ngoài ra, không có cách nào để đi theo con đường khác (từ một chuỗi đến đối tượng enum) mà có lẽ sẽ được yêu cầu tại một số điểm.
Adrian Smith

ghi đè toString không ảnh hưởng đến valueOf (), phải không?
Dmitriusan

69

Sử dụng name()phương pháp của nó :

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Strings.ONE.name());
    }
}

enum Strings {
    ONE, TWO, THREE
}

sản lượng ONE.


17
Vâng, nhưng Strings.STRING_ONE.name()mang lại "STRING_ONE", không phải "MỘT". Đây đơn giản không phải là một câu trả lời hay. Bạn không thể có bất kỳ Chuỗi nào không phải là định danh Java hợp lệ, v.v.
Mark Peters

2
@Mark, đúng, nó không thể xử lý bất kỳ nhân vật. Nếu OP chỉ muốn một char duy nhất, giải pháp này đơn giản hơn so với đề xuất của The Elite Gent Quý ông. Nhưng thực sự: nếu phạm vi các ký tự vượt quá các ký tự mà một định danh Java hợp lệ có thể có, thì đây là điều không nên. Điểm tốt.
Bart Kiers

Rất hợp lý khi có một quy ước đặt tên nội bộ cho một enum khác với những gì người ta muốn hiển thị với toString () (đặc biệt nếu người dùng nhìn thấy đầu ra), vì vậy tôi không nghĩ đây hoàn toàn là OP tìm kiếm.
Michael McGowan

17
Kết quả từ name()có thể bị ảnh hưởng bởi một chương trình obfuscator. Tôi đã gặp một vấn đề tương tự một thời gian trước đây. Chẳng hạn, với Proguard, bạn cần giải quyết vấn đề này. Xem Xử lý các lớp học liệt kê
noisecapella

Thật tuyệt vời. Hoạt động với các giá trị như: var_name, var_superlong_but_not_toooooo_long_name, thậm chí vv (không có dấu ba chấm)

18

Hoặc đặt tên enum giống với chuỗi bạn muốn hoặc, nói chung, bạn có thể liên kết các thuộc tính tùy ý với các giá trị enum của bạn:

enum Strings {
   STRING_ONE("ONE"), STRING_TWO("TWO");
   private final String stringValue;
   Strings(final String s) { stringValue = s; }
   public String toString() { return stringValue; }
   // further methods, attributes, etc.
}

Điều quan trọng là phải có các hằng số ở trên cùng và các phương thức / thuộc tính ở phía dưới.


Và cũng để có một nhà xây dựng tư nhân .
Buhake Sindi

1
Các nhà xây dựng enum là riêng tư theo mặc định và không yêu cầu sửa đổi truy cập. Nhưng đó là một điểm tốt về các công cụ sửa đổi truy cập nói chung, tôi đã cập nhật mã của mình để thêm chúng vào thuộc tính và trình truy cập.
Adrian Smith

15

Tùy thuộc vào ý của bạn bằng cách "sử dụng chúng làm Chuỗi", bạn có thể không muốn sử dụng enum ở đây. Trong hầu hết các trường hợp, giải pháp được đề xuất bởi The Elite Gent Quý ông sẽ cho phép bạn sử dụng chúng thông qua các phương thức toString của họ, ví dụ như trong System.out.println(STRING_ONE)hoặc String s = "Hello "+STRING_TWO, nhưng khi bạn thực sự cần Chuỗi (ví dụ STRING_ONE.toLowerCase()), bạn có thể thích xác định chúng là hằng số:

public interface Strings{
  public static final String STRING_ONE = "ONE";
  public static final String STRING_TWO = "TWO";      
}

5
thực ra đây là điều tôi đang cố tránh ...!
Dori

Trên thực tế, nếu họ cũng muốn toLowerCase()giải pháp của tôi, họ có thể đi Strings.STRING_TWO.toString().toLowerCase().
Buhake Sindi

Chắc chắn, nhưng đó không phải là sử dụng chúng như các chuỗi như tôi đã giải thích nó. Vì Rrackham dường như không yêu cầu sử dụng đó, tất nhiên anh ta nên sử dụng giải pháp enum được đề xuất.
hd42

6
Bạn không nên sử dụng interfacethay cho một finallớp với hàm privatetạo. Đó là một thực tế nản lòng.
Aleks N.

1
@mils, các giải pháp sử dụng enums cũng hoạt động tốt trong một công tắc. Tôi chỉ đề xuất giải pháp này nếu cần chuỗi trực tiếp.
hd42

8

Bạn có thể sử dụng nó cho chuỗi Enum

public enum EnumTest {
    NAME_ONE("Name 1"),
    NAME_TWO("Name 2");

    private final String name;

    /**
     * @param name
     */
    private EnumTest(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Và gọi từ phương thức chính

public class Test {
    public static void main (String args[]){
        System.out.println(EnumTest.NAME_ONE.getName());
        System.out.println(EnumTest.NAME_TWO.getName());
    }
}

5

Nếu bạn không muốn sử dụng các hàm tạo và bạn muốn có một tên đặc biệt cho phương thức này, hãy thử nó:

public enum MyType {
  ONE {
      public String getDescription() {
          return "this is one";
      }
  },    
  TWO {
      public String getDescription() {
          return "this is two";
      }
  };

  public abstract String getDescription();
}

Tôi nghi ngờ rằng đây là giải pháp nhanh nhất . Không cần sử dụng biến cuối cùng .


nhưng với cái này bạn vẫn phải gọi getDes mô tả () trong đó người hỏi muốn gọi ONE hoặc truy cập nó như một hằng số.
kinsley kajiva

Tôi thích điều này. Điều gì sẽ xảy ra nếu nó cần chấp nhận thêm thông tin? Với giải pháp này, chỉ cần thêm các phương thức trừu tượng được bảo vệ và ghi đè lên nó. Hơn nữa không cần ghi đè phương thức toString (). Nó sạch sẽ và có thể được chấp nhận là câu trả lời tốt nhất.
Arundev

0

Nhận và thiết lập với các giá trị mặc định.

public enum Status {

    STATUS_A("Status A"),  STATUS_B("Status B"),

    private String status;

    Status(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }
}
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.