Question

Regarding enums in java how I understood is

Sample enum

public enum Strategy {

    STRATEGY_A {
        @Override
        void execute(){
            System.out.print("Executing strategy A");
        }
    },

    STRATEGY_B {
        @Override
        void execute(){
            System.out.print("Executing strategy B");
        }
    };

    abstract void execute();
}

This would be compiled to something like

public abstract class Strategy extends java.lang.Enum<Strategy> {
  public static final Strategy STRATEGY_A;
  public static final Strategy STRATEGY_B;
  private static final Strategy[] $VALUES;
  public static Strategy[] values();
  public static Strategy valueOf(java.lang.String);
  private Strategy();
  abstract void execute();
  Strategy(java.lang.String, int, Strategy$1);
  static {};
}

and the enum STRATEGY_A would be like a sub class which extends its base class STRATEGY

final class Strategy$1 extends Strategy {
  Strategy$1(java.lang.String, int);
  void execute();
}

I could get the above with the help of javap by reading the class file.

As far as I understand, enum fields (or) constants are nothing but class objects of enum. For example

public enum Fruits {
APPLE;    //APPLE would be the instance of Fruits
ORANGE;   //ORANGE would be the instance of Fruits
GRAPES;   //GRAPES would be the instance of Fruits
}

But why does the enum filed STRATEGY_A and STRATEGY_B extend the base class or base enum STRATEGY? I couldn't differentiate between "enum fields (APPLE, ORANGE)" and "enum sub classes (STRATEGY_A, STRATEGY_B)" like the above. What do they really mean by each other?

EDIT

All these doubts came while implementing strategy pattern with enum.

STRATEGY PATTERN.

Was it helpful?

Solution

How would you have written the enum class as if the enum structure had not been added in Java? You would implement it like this:

public abstract class Strategy {
    public final static Strategy
        STRATEGY_A = new Strategy(){
            @Override
            void execute(){
                System.out.print("Executing strategy A");
            }
        },
        STRATEGY_B = new Strategy(){
            @Override
            void execute(){
                System.out.print("Executing strategy B");
            }
        };

    abstract void execute();
}

When you compile this class, it will also generate new classes (following is from javap):

public abstract class Strategy {
  public static final Strategy STRATEGY_A;
  public static final Strategy STRATEGY_B;
  public Strategy();
  abstract void execute();
  static {};
}
final class Strategy$1 extends Strategy {
  Strategy$1();
  void execute();
}
final class Strategy$2 extends Strategy {
  Strategy$2();
  void execute();
}

Essentially this is the same as what you got for the enum:

public abstract class Strategy extends java.lang.Enum<Strategy> {
  public static final Strategy STRATEGY_A;
  public static final Strategy STRATEGY_B;
  public static Strategy[] values();
  public static Strategy valueOf(java.lang.String);
  abstract void execute();
  Strategy(java.lang.String, int, Strategy$1);
  static {};
}
final class Strategy$1 extends Strategy {
  Strategy$1(java.lang.String, int);
  void execute();
}
final class Strategy$2 extends Strategy {
  Strategy$2(java.lang.String, int);
  void execute();
}

Would it look better if you view them as anonymous classes?

Now, why do non-overridden classes do not have implementations? This is because there are no anonymous classes needed.

Similarly, for enums that only have some fields overriding the value, only those fields will have subclasses. See this Foo.java file:

public enum Foo{
    FOO_A,
    FOO_B,
    FOO_C{
        @Override public void bar(){ System.out.println(2); }
    },
    FOO_D{
        @Override public void bar(){ System.out.println(2); }
    },
    FOO_E{
        @Override public void bar(){ System.out.println(3); }
    };
    public void bar(){ System.out.println(1); }
}

It is compiled into:

final class Foo$1 extends Foo {
  Foo$1(java.lang.String, int);
  public void bar();
}
final class Foo$2 extends Foo {
  Foo$2(java.lang.String, int);
  public void bar();
}
final class Foo$3 extends Foo {
  Foo$3(java.lang.String, int);
  public void bar();
}
public class Foo extends java.lang.Enum<Foo> {
  public static final Foo FOO_A;
  public static final Foo FOO_B;
  public static final Foo FOO_C;
  public static final Foo FOO_D;
  public static final Foo FOO_E;
  public static Foo[] values();
  public static Foo valueOf(java.lang.String);
  public void bar();
  Foo(java.lang.String, int, Foo$1);
  static {};
}

This is similar to the output of this class:

public class Foo{
    public final static Foo FOO_A = new Foo(),
    FOO_B = new Foo(),
    FOO_C = new Foo(){
        @Override public void bar(){ System.out.println(2); }
    },
    FOO_D = new Foo(){
        @Override public void bar(){ System.out.println(2); }
    },
    FOO_E = new Foo(){
        @Override public void bar(){ System.out.println(3); }
    };
    public void bar(){ System.out.println(1); }
}

So in the end, your question doesn't stand -- there is no need to differentiate subclasses or not, because they just behave like anonymous classes. If you understand subclassing well enough, you would understand that there is no difference between subclass or not if you use it properly (which includes not using reflections).

OTHER TIPS

The individual fields in this case can only be instances of subclasses because they have different implementations of the execute() method. If they only had fields with different values, they could all be instances of the same class, but if they have different behaviour, then that is only possible with subclasses.

With the help of @PEMapModder's answer I could make clear the following

    public enum Strategy {

    STRATEGY_A {
        @Override
        void execute(){
            System.out.print("Executing strategy A");
        }
    },

    STRATEGY_B {
        @Override
        void execute(){
            System.out.print("Executing strategy B");
        }
    };

    abstract void execute();
}

This is the same as

    public abstract class Strategy {
    public final static Strategy
        STRATEGY_A = new Strategy(){
            @Override
            void execute(){
                System.out.print("Executing strategy A");
            }
        },
        STRATEGY_B = new Strategy(){
            @Override
            void execute(){
                System.out.print("Executing strategy B");
            }
        };

    abstract void execute();
}

So it is like Anonymous Inner Classes which is useful when making an instance of an object with certain additional properties for the class such as overloading or overriding its methods, without actually having to subclass a class.

A better example for anonymous inner class and why it is more useful is explained well here.

Licensed under: CC-BY-SA with attribution
scroll top