Programing

공개 정적 최종 필드가있는 클래스와 Java 열거의 장점은 무엇입니까?

lottogame 2020. 6. 28. 18:27
반응형

공개 정적 최종 필드가있는 클래스와 Java 열거의 장점은 무엇입니까?


C #에 익숙하지만 Java에서 더 많은 작업을 시작합니다. Java의 열거 형은 기본적으로 C #의 열거 형과 동일하지만 실제로는 그렇지 않습니다. 처음에는 Java 열거 형에 매우 유리한 여러 조각의 데이터가 포함될 수 있음을 알게되어 기뻤습니다 ( http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ). 그러나 그 이후로 열거 형 요소에 특정 값을 쉽게 할당 할 수있는 능력과 적절한 노력없이 정수를 열거 형으로 변환하는 기능과 같이 C #에서 사소한 많은 기능이 누락되었습니다. 즉 정수 값을 일치하는 Java Enum으로 변환하십시오 .

그래서 내 질문은 이것입니다 : 많은 공개 정적 최종 필드가있는 클래스에 비해 Java 열거에 이점이 있습니까? 아니면 더 간단한 구문을 제공합니까?

편집 : 더 명확하게하겠습니다. 같은 유형 의 공개 정적 최종 필드 많은 클래스에 비해 Java 열거 형의 이점은 무엇입니까 ? 예를 들어 첫 번째 링크의 행성 예에서 다음과 같은 공용 상수를 사용하는 클래스보다 열거 형의 장점은 무엇입니까?

public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);

내가 알 수있는 한, casablanca의 대답은 이것을 충족시키는 유일한 것입니다.


기술적으로 열거 형을 여러 유형의 상수가있는 클래스로 볼 수 있으며 실제로는 열거 형 상수가 내부적으로 구현되는 방식입니다. enum그러나를 사용 하면와 같이 스스로 구현 해야하는 유용한 메소드 ( Enum javadoc )가 제공됩니다 Enum.valueOf.


  1. 안전 및 가치 안전을 입력하십시오.
  2. 싱글 톤 보장.
  3. 메소드를 정의하고 재정의하는 기능.
  4. 의 값을 사용할 수있는 기능 switchcase자격없이 문을.
  5. 다음을 통한 값의 내장 순차 ordinal().
  6. 가치가 아닌 이름으로 직렬화하여 미래를 보장합니다.
  7. EnumSet그리고 EnumMap수업.

아무도 switch진술 에서 그것들을 사용할 수있는 능력을 언급하지 않았다 . 나는 그것을 넣을 것이다.

이것은 임의로 복잡한 열거 형을 사용하여 instanceof잠재적으로 혼란스러운 if시퀀스 또는 문자열이 아닌 / int 스위칭 값 을 사용하지 않고 깔끔하게 사용할 수 있습니다 . 표준 예는 상태 머신입니다.


주요 장점은 형식 안전성입니다. 상수 세트를 사용하면 동일한 내장 유형의 모든 값을 사용하여 오류가 발생할 수 있습니다. 열거 형을 사용하면 적용 가능한 값만 사용할 수 있습니다.

예를 들어

public static final int SIZE_SMALL  = 1;
public static final int SIZE_MEDIUM = 2;
public static final int SIZE_LARGE  = 3;

public void setSize(int newSize) { ... }

obj.setSize(15); // Compiles but likely to fail later

vs

public enum Size { SMALL, MEDIUM, LARGE };

public void setSize(Size s) { ... }

obj.setSize( ? ); // Can't even express the above example with an enum

혼란이 적습니다. Font예를 들어 보자 . Font원하는 이름 , 크기 및 스타일 ( new Font(String, int, int)) 을 갖는 생성자가 있습니다. 오늘날까지 스타일이나 크기가 먼저되는지 기억이 나지 않습니다. 경우 Font사용했다 enum그것의 다른 스타일의 모든을 ( PLAIN, BOLD, ITALIC, BOLD_ITALIC), 생성자는 같을 것이다 Font(String, Style, int)혼란을 방지. 불행히도 클래스가 만들어 enum졌을 때 s는 없었고 FontJava는 역 호환성을 유지해야하기 때문에 항상이 모호함에 시달릴 것입니다.

물론 이것은 상수 enum대신에 사용하는 인수 일뿐 public static final입니다. 열거 형은 싱글 톤에 적합 하며 기본 동작을 구현하면서 나중에 사용자 정의 할 수 있습니다 (IE 전략 패턴 ). 후자의 예는 다음 java.nio.file의 ' OpenOptionStandardOpenOption개발자가 자신이 아닌 표준을 만들려는 경우 :은 OpenOption, 그가 할 수.


여기에는 많은 좋은 대답이 있지만 열거 형을 위해 특별히 Collection API 클래스 / 인터페이스의 구현고도로 최적화 되었다는 언급은 없습니다 .

These enum specific classes only accept Enum instances (the EnumMap only accept Enums only as keys), and whenever possible, they revert to compact representation and bit manipulation in their implementation.

What does this mean?

If our Enum type has no more that 64 elements (most of real-life Enum examples will qualify for this), the implementations store the elements in a single long value, each Enum instance in question will be associated with a bit of this 64-bit long long. Adding an element to an EnumSet is simply just setting the proper bit to 1, removing it is just setting that bit to 0. Testing if an element is in the Set is just one bitmask test! Now you gotta love Enums for this!


The first benefit of enums, as you have already noticed, is syntax simplicity. But the main point of enums is to provide a well-known set of constants which, by default, form a range and help to perform more comprehensive code analysis through type & value safety checks.

Those attributes of enums help both a programmer and a compiler. For example, let's say you see a function that accepts an integer. What that integer could mean? What kind of values can you pass in? You don't really know right away. But if you see a function that accepts enum, you know very well all possible values you can pass in.

For the compiler, enums help to determine a range of values and unless you assign special values to enum members, they are well ranges from 0 and up. This helps to automatically track down errors in the code through type safety checks and more. For example, compiler may warn you that you don't handle all possible enum values in your switch statement (i.e. when you don't have default case and handle only one out of N enum values). It also warns you when you convert an arbitrary integer into enum because enum's range of values is less than integer's and that in turn may trigger errors in the function that doesn't really accept an integer. Also, generating a jump table for the switch becomes easier when values are from 0 and up.

This is not only true for Java, but for other languages with a strict type-checking as well. C, C++, D, C# are good examples.


example:

public class CurrencyDenom {
   public static final int PENNY = 1;
 public static final int NICKLE = 5;
 public static final int DIME = 10;
public static final int QUARTER = 25;}

Limitation of java Constants

1) No Type-Safety: First of all it’s not type-safe; you can assign any valid int value to int e.g. 99 though there is no coin to represent that value.

2) No Meaningful Printing: printing value of any of these constant will print its numeric value instead of meaningful name of coin e.g. when you print NICKLE it will print "5" instead of "NICKLE"

3) No namespace: to access the currencyDenom constant we need to prefix class name e.g. CurrencyDenom.PENNY instead of just using PENNY though this can also be achieved by using static import in JDK 1.5

Advantage of enum

1) Enums in Java are type-safe and has there own name-space. It means your enum will have a type for example "Currency" in below example and you can not assign any value other than specified in Enum Constants.

public enum Currency {PENNY, NICKLE, DIME, QUARTER};

Currency coin = Currency.PENNY; coin = 1; //compilation error

2) Enum in Java are reference type like class or interface and you can define constructor, methods and variables inside java Enum which makes it more powerful than Enum in C and C++ as shown in next example of Java Enum type.

3) You can specify values of enum constants at the creation time as shown in below example: public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)}; But for this to work you need to define a member variable and a constructor because PENNY (1) is actually calling a constructor which accepts int value , see below example.

public enum Currency {
    PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
    private int value;

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

Reference: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html


enum Benefits:

  1. Enums are type-safe, static fields are not
  2. There is a finite number of values (it is not possible to pass non-existing enum value. If you have static class fields, you can make that mistake)
  3. Each enum can have multiple properties (fields/getters) assigned - encapsulation. Also some simple methods: YEAR.toSeconds() or similar. Compare: Colors.RED.getHex() with Colors.toHex(Colors.RED)

"such as the ability to easily assign an enum element a certain value"

enum EnumX{
  VAL_1(1),
  VAL_200(200);
  public final int certainValue;
  private X(int certainValue){this.certainValue = certainValue;}
}

"and consequently the ability to convert an integer to an enum without a decent amount of effort" Add a method converting int to enum which does that. Just add static HashMap containing the mapping.

If you really want to convert ord=VAL_200.ordinal() back to val_200 just use: EnumX.values()[ord]


An enum is implictly final, with a private constructors, all its values are of the same type or a sub-type, you can obtain all its values using values(), gets its name() or ordinal() value or you can look up an enum by number or name.

You can also define subclasses (even though notionally final, something you can't do any other way)

enum Runner implements Runnable {
    HI {
       public void run() {
           System.out.println("Hello");
       }
    }, BYE {
       public void run() {
           System.out.println("Sayonara");
       }
       public String toString() {
           return "good-bye";
       }
    }
 }

 class MYRunner extends Runner // won't compile.

Another important difference is that java compiler treats static final fields of primitive types and String as literals. It means these constants become inline. It's similar to C/C++ #define preprocessor. See this SO question. This is not the case with enums.


You get compile time checking of valid values when you use an enum. Look at this question.


The biggest advantage is enum Singletons are easy to write and thread-safe :

public enum EasySingleton{
    INSTANCE;
}

and

/**
* Singleton pattern example with Double checked Locking
*/
public class DoubleCheckedLockingSingleton{
     private volatile DoubleCheckedLockingSingleton INSTANCE;

     private DoubleCheckedLockingSingleton(){}

     public DoubleCheckedLockingSingleton getInstance(){
         if(INSTANCE == null){
            synchronized(DoubleCheckedLockingSingleton.class){
                //double checking Singleton instance
                if(INSTANCE == null){
                    INSTANCE = new DoubleCheckedLockingSingleton();
                }
            }
         }
         return INSTANCE;
     }
}

both are similar and it handled Serialization by themselves by implementing

//readResolve to prevent another instance of Singleton
    private Object readResolve(){
        return INSTANCE;
    }

more


I think an enum can't be final, because under the hood compiler generates subclasses for each enum entry.

More information From source


There are many advantages of enums that are posted here, and I am creating such enums right now as asked in the question. But I have an enum with 5-6 fields.

enum Planet{
EARTH(1000000, 312312321,31232131, "some text", "", 12),
....
other planets
....

In these kinds of cases, when you have multiple fields in enums, it is much difficult to understand which value belongs to which field as you need to see constructor and eye-ball.

Class with static final constants and using Builder pattern to create such objects makes it more readable. But, you would lose all other advantages of using an enum, if you need them. One disadvantage of such classes is, you need to add the Planet objects manually to the list/set of Planets.

I still prefer enum over such class, as values() comes in handy and you never know if you need them to use in switch or EnumSet or EnumMap in future :)

참고URL : https://stackoverflow.com/questions/9969690/whats-the-advantage-of-a-java-enum-versus-a-class-with-public-static-final-fiel

반응형