Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
You can declare an enum inside a Java class. The precise term is a nested enum, not an inner class: member enums are implicitly static, so they do not need an instance of the enclosing class and cannot implicitly access its instance fields.
Declare and use a member enum
Put the enum declaration inside the class whose API or implementation it belongs to. Outside that class, refer to it through the enclosing type:
public final class Order {
public enum Status {
NEW,
PAID,
SHIPPED,
CANCELLED
}
private Status status = Status.NEW;
public Status status() {
return status;
}
public void markPaid() {
status = Status.PAID;
}
}
Order order = new Order();
Order.Status current = order.status();
if (current == Order.Status.NEW) {
order.markPaid();
}
Inside Order, Status.NEW is enough. Code outside the class normally writes Order.Status.NEW. You can also import the nested type with import com.example.Order.Status; and then use Status.PAID. A static import such as import static com.example.Order.Status.PAID; is legal, but can make the enum’s ownership less apparent.
A minimal standalone example can be saved as Order.java, then compiled and run with javac Order.java and java Order. If the main method assigns Order.Status.PAID and prints it, the output is PAID. For reproducible builds, set the project’s intended Java release rather than relying on the installed JDK; for example, javac --release 17 Order.java.
Nested enum versus inner class
Java uses inner class for a non-static nested class. An enum declared as a member of another class is different: it is implicitly static and is therefore a nested type, not an inner class. The distinction affects whether the nested type has an enclosing object.
class Outer {
private int value = 42;
class Inner {
int readValue() {
return value;
}
}
enum Kind {
A
}
}
Inner can read the particular Outer instance’s value. Kind has no such implicit connection. It can be used without constructing an Outer object:
Outer.Kind kind = Outer.Kind.A;
You cannot construct an enum instance with new; enum constants are the instances:
new Outer.Kind(); // Does not compile
Adding static to a member enum is allowed but redundant:
class Response {
enum Code { OK, NOT_FOUND }
}
// Equivalent declaration:
class ResponseWithExplicitModifier {
static enum Code { OK, NOT_FOUND }
}
Here, static means the nested type does not require an enclosing instance. It does not turn enum constants into ordinary mutable static fields. These language rules are specified in the Java Language Specification, Chapter 8.
Choose visibility and placement deliberately
A member enum follows member access rules. Its accessibility is also bounded by the accessibility of its enclosing class.
Rank #2
public: accessible wherever the enclosing class is accessible.protected: accessible under Java’s protected-member rules.private: accessible only within the enclosing top-level class.- No modifier: package-private.
A private nested enum can keep implementation choices out of a class’s public API. A public nested enum is part of that API: clients may compile against it, so renaming the enclosing type, moving the enum, or changing its constants can affect them.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use a nested enum when the type belongs conceptually to one abstraction and the enclosing class is a useful namespace, as in Payment.Status or HttpRequest.Method. Choose a top-level enum if unrelated classes use it or it has an independent identity, such as a package-level PaymentStatus. A local enum, covered below, fits a finite set used only in one method or block.
Add fields, constructors, methods, and interfaces
Enum constants come first. If the enum declares fields, constructors, methods, or other members after its constants, terminate the constant list with a semicolon.
public final class FileEntry {
public enum Kind {
FILE("file"),
DIRECTORY("directory"),
SYMBOLIC_LINK("symlink");
private final String label;
Kind(String label) {
this.label = label;
}
public String label() {
return label;
}
}
}
Use FileEntry.Kind.DIRECTORY.label() to retrieve the label. Application code cannot call the enum constructor; the runtime creates the declared constants. An enum cannot extend an arbitrary class because every enum already extends java.lang.Enum, but it can implement interfaces. See Oracle’s enum tutorial for the declaration rules.
For example, a nested enum can implement an interface declared alongside it:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
public final class Payment {
public interface Displayable {
String displayName();
}
public enum Status implements Displayable {
PENDING("Pending"),
PAID("Paid"),
FAILED("Failed");
private final String label;
Status(String label) {
this.label = label;
}
@Override
public String displayName() {
return label;
}
}
}
Use a constant-specific class body when each constant genuinely supplies its own polymorphic implementation:
enum Operation {
ADD {
@Override
int apply(int left, int right) {
return left + right;
}
},
MULTIPLY {
@Override
int apply(int left, int right) {
return left * right;
}
};
abstract int apply(int left, int right);
}
For short behavior, a single method with a switch over the constants is often simpler. Choose the constant-specific form when keeping behavior with each constant improves the design, rather than merely to avoid a small switch.
Use enum methods without treating them as stable identifiers
Enum types provide compiler-generated methods such as values() and valueOf(String), in addition to methods inherited from Enum.
values()returns the constants in declaration order.valueOf("PAID")looks up an exact, case-sensitive constant name; an unknown name causes an exception.name()returns the declared identifier exactly.toString()can be overridden, so do not assume it always equalsname().ordinal()is the zero-based declaration position.
For example, Order.Status.values() lists every status, while Order.Status.valueOf("PAID") returns the PAID constant. The Java 21 Enum API documentation specifies these methods and their behavior.
Recommended Free Tools
Do not use ordinal() as a database key, business code, or persisted representation: inserting or reordering constants changes the position. Give a constant an explicit value instead:
enum Priority {
LOW(10),
MEDIUM(20),
HIGH(30);
private final int code;
Priority(int code) {
this.code = code;
}
public int code() {
return code;
}
}
Likewise, use name() when you specifically need the declared Java identifier; use an explicit field when a value must remain stable for an external API, file, or database.
Parse external text with an explicit policy
Calling valueOf(input) directly is suitable only when input is already guaranteed to match a constant name exactly. If input comes from a user or external system, decide how to handle case, surrounding whitespace, aliases, and unknown values. One simple case-insensitive parser is:
Rank #4
enum Status {
NEW,
PAID,
SHIPPED;
static Optional<Status> parse(String text) {
if (text == null) {
return Optional.empty();
}
for (Status status : values()) {
if (status.name().equalsIgnoreCase(text.trim())) {
return Optional.of(status);
}
}
return Optional.empty();
}
}
For repeated lookups in a large enum, a map can be built once, using a defined normalization rule such as Locale.ROOT. If the external representation must survive renaming Java constants, give each constant an explicit external code instead of treating its name as a contract.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsSwitch on enum constants
A traditional switch statement uses the constants by their unqualified names in the case labels:
switch (order.status()) {
case NEW:
startPayment();
break;
case PAID:
shipOrder();
break;
case SHIPPED:
notifyCustomer();
break;
case CANCELLED:
cancelFulfillment();
break;
}
On Java 14 and later, switch expressions can produce a value; this example uses arrow labels:
String message = switch (order.status()) {
case NEW -> "Awaiting payment";
case PAID -> "Ready to ship";
case SHIPPED -> "In transit";
case CANCELLED -> "Cancelled";
};
A switch expression over a known enum can be exhaustive without a default. That lets the compiler flag code that needs attention when a constant is added. A default branch can be appropriate when a component must defensively handle enum evolution from another module, but it can also conceal an unhandled new case. Choose based on whether compile-time pressure or runtime fallback is the safer behavior for the application.
Declare a local enum when the type is truly local
Java 16 and later allow a local enum declaration inside a method or block:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchclass Lexer {
void scan(String input) {
enum TokenType {
WORD,
NUMBER,
SYMBOL
}
TokenType type = TokenType.WORD;
System.out.println(type);
}
}
The type is visible only in its enclosing block and, like other nested enums, does not capture a local variable or enclosing instance. Do not write static enum for a local enum; the explicit modifier is not permitted. Code compiled for Java 15 or earlier cannot use local enums. Java 16’s changes are described in JEP 395.
Best Value
To check installed versions, run java --version and javac --version. To compile a local-enum example using Java 16 language features, use an appropriate release target, for example javac --release 16 Lexer.java. If other methods or tests need to name the type, make it a member enum instead.
Enums inside inner classes and older Java versions
An enum may be declared inside an inner class in modern Java:
class Outer {
class Inner {
enum State {
ACTIVE,
INACTIVE
}
}
}
Outer.Inner.State state = Outer.Inner.State.ACTIVE;
This is a version-sensitive case. Older Java rules prohibited static members in inner classes, which also excluded implicitly static member enums. Java 16 relaxed those restrictions; current language rules allow the declaration. The enum still does not capture an Inner instance or gain implicit access to its instance fields. For the historical change, see the Java 16 preview specification; for the current rules, see the current Java Language Specification. If supporting older source levels, avoid this form.
Reflection, binary names, and serialization
In source code, use a nested type’s canonical name, such as com.example.Outer.Status. Its binary name commonly uses a dollar sign, such as com.example.Outer$Status. Ordinary Java code should refer to it as Outer.Status; avoid hard-coding binary names unless working with reflection, class loading, or bytecode tools.
When a constant has a constant-specific class body, constant.getClass() may identify a generated subclass rather than the enum declaration itself. Use constant.getDeclaringClass() when you need the enum type that declared the constant.
Java enum serialization has special rules: a constant’s serialized identity is based on its name, and enum serialization cannot be customized in the same way as ordinary serializable classes. Renaming or removing a constant can therefore affect previously serialized data. For durable database or wire formats, use an explicit code and define how unknown values are handled.
Quick Recap
Common compile-time and design mistakes
- Trying to instantiate a constant:
new Order.Status()is invalid. Refer to a declared value such asOrder.Status.PAID. - Reading an enclosing instance field: a nested enum has no implicit enclosing object. Pass the enclosing object as an argument if that dependency is intentional, or reconsider where the behavior belongs.
- Writing
staticon a local enum: declare the enum directly in the block without that modifier. - Omitting the semicolon before members: use
PAID;before declaring fields or methods after the constants. - Passing differently cased input to
valueOf:valueOf("paid")does not matchPAID; normalize or parse deliberately. - Persisting ordinals or assuming
toString()is fixed: use explicit codes for stable external representations.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.

