공개 정적 최종 필드가있는 클래스와 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
.
- 안전 및 가치 안전을 입력하십시오.
- 싱글 톤 보장.
- 메소드를 정의하고 재정의하는 기능.
- 의 값을 사용할 수있는 기능
switch
문case
자격없이 문을. - 다음을 통한 값의 내장 순차
ordinal().
- 가치가 아닌 이름으로 직렬화하여 미래를 보장합니다.
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는 없었고 Font
Java는 역 호환성을 유지해야하기 때문에 항상이 모호함에 시달릴 것입니다.
물론 이것은 상수 enum
대신에 사용하는 인수 일뿐 public static final
입니다. 열거 형은 싱글 톤에 적합 하며 기본 동작을 구현하면서 나중에 사용자 정의 할 수 있습니다 (IE 전략 패턴 ). 후자의 예는 다음 java.nio.file
의 ' OpenOption
와 StandardOpenOption
개발자가 자신이 아닌 표준을 만들려는 경우 :은 OpenOption
, 그가 할 수.
여기에는 많은 좋은 대답이 있지만 열거 형을 위해 특별히 Collection API 클래스 / 인터페이스의 구현 이 고도로 최적화 되었다는 언급은 없습니다 .
These enum specific classes only accept Enum
instances (the EnumMap
only accept Enum
s 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 Enum
s 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:
- Enums are type-safe, static fields are not
- 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)
- 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;
}
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 :)
'Programing' 카테고리의 다른 글
iPhone TableView 셀에서 셀의 오른쪽에 작은 화살표 추가 (0) | 2020.06.28 |
---|---|
Traceur를 사용하여 ES6 클래스에서 전용 메소드를 구현하는 방법 (0) | 2020.06.28 |
데이터베이스의 MongoDB 덤프를 어떻게 만듭니 까? (0) | 2020.06.28 |
Resharper 4.x 이상 비활성화 및 제거 (0) | 2020.06.28 |
T-SQL에서 문자열의 마지막 문자를 제거 하시겠습니까? (0) | 2020.06.28 |