Where Is the Documentation for the Values() Method of Enum

Where is the documentation for the values() method of Enum?

You can't see this method in javadoc because it's added by the compiler.

Documented in three places :

  • Enum Types, from The Java Tutorials

The compiler automatically adds some special methods when it creates
an enum. For example, they have a static values method that returns an
array containing all of the values of the enum in the order they are
declared. This method is commonly used in combination with the
for-each construct to iterate over the values of an enum type.

  • Enum.valueOf class
    (The special implicit values method is mentioned in description of valueOf method)

All the constants of an enum type can be obtained by calling the implicit public static T[] values() method of that type.

  • Enum Types, Section 8.9, Java Language Specification

The values function simply list all values of the enumeration.

From whence cometh Enum.values()?

The values() method is part of the definition of the enum type. Not to be confused with the Enum base class. The formal definition is in the Section 8.9 of the JLS which does specify the order returned matches the order in which they are declared.

Enum type in Java : values() in for each loop

The values() method returns an array of enum values. In Java you can iterate over array using for(Object obj : arr) syntax. It's just a syntactic sugar. During the compilation the implicit int local variable will be created and the cycle will be rewritten like this:

Planet[] vals = Planet.values();
for(int i=0; i<vals.length; i++) {
Planet p = vals[i];
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}

values() of a Enum

You can't see it because it is not defined on the Enum class, but rather on specific subclasses of Enum (i.e. your enum's class).

This is because static methods are not polymorphic: a values method on the subclass would not override the method in the superclass, but rather hide it.

You can get the enum constants for a class reflectively:

YourEnum.class.getEnumConstants()

Why I can not get .values() from Enum object class?

Enum#values is a method that is generated by the compiler, so you cannot use it at compile time unless you pass in a specific enum and not Enum<?>.

See: https://stackoverflow.com/a/13659231/7294647

One solution would be to pass in a Class<E extends Enum<E>> instead and use Class#getEnumConstants:

public static <E extends Enum<E>> Boolean enumContains(Class<E> clazz, String valueString){
return toStringList(clazz.getEnumConstants()).contains(valueString.toUpperCase());
}

If you have an enum named MyEnum, then you can simply pass in MyEnum.class as the first argument.

java Enum valueOf has two parameters?

You can just examine the bytecode to see what happens when an enum is compiled:

public enum TestEnum {A, B}

And the bytecode of valueOf:

// access flags 0x9
public static valueOf(Ljava/lang/String;)LTestEnum;
L0
LINENUMBER 1 L0
LDC LTestEnum;.class
ALOAD 0
INVOKESTATIC java/lang/Enum.valueOf (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
CHECKCAST TestEnum
ARETURN
L1
LOCALVARIABLE name Ljava/lang/String; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 1

I am no expert in byte code but you can see that the line:

INVOKESTATIC java/lang/Enum.valueOf (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;

In fact invokes java.lang.Enum.valueOf. A java equivalent would look like this:

public static TestEnum myValueOf(String name) {
return Enum.valueOf(TestEnum.class, name);
}

And the bytecode confirms this:

// access flags 0x9
public static myValueOf(Ljava/lang/String;)LTestEnum;
L0
LINENUMBER 6 L0
LDC LTestEnum;.class
ALOAD 0
INVOKESTATIC java/lang/Enum.valueOf (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
CHECKCAST TestEnum
ARETURN
L1
LOCALVARIABLE name Ljava/lang/String; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 1

Comparing these two snippets you can see the difference is... yes, the name (and the line number):

Sample Image

How to get number of possible items of an Enum?

Yes you can use the Enum.values() method to get an array of Enum values then use the length property.

public class Main {
enum WORKDAYS { Monday, Tuesday, Wednesday, Thursday, Friday; }

public static void main(String[] args) {
System.out.println(WORKDAYS.values().length);
// prints 5
}
}

http://ideone.com/zMB6pG

How to @link to a Enum Value using Javadoc

The # style works for me:

{@link Planet#EARTH}

The key is that the Planet package must be imported, or Planet must be fully qualified - i.e.:

{@link com.yourpackage.Planet#EARTH}

How to access a specific member in Java enum by Index value?

Your code nearly works. Take a close look at the method signature of Enum#values (documentation).

It is no method that accepts an argument, it returns the whole array. So you need to shift the access after the method as array-access:

Season.values()[2]

You should avoid accessing Enum by index. They depend on their order in the code. If you do some refactoring like "sort project alphabetical":

public enum Season {
FALL, // 3 -> 0
SPRING, // 1 -> 1
SUMMER, // 2 -> 2
WINTER // 0 -> 3
}

or later add some values to your enum without remembering your order-depend code, then you will break your code. Instead you may setup a Map<Integer, Season>:

Map<Integer, Season> indexToSeason = new HashMap<>();
indexToSeason.put(0, Season.WINTER);
indexToSeason.put(1, Season.SPRING);
indexToSeason.put(2, Season.SUMMER);
indexToSeason.put(3, Season.FALL);

And then use that map for access:

public Season getSeasonByIndex(int index) {
return indexToSeason.get(index);
}


Related Topics



Leave a reply



Submit