0

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.

4

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).

  • Explained really really well @PEMapModder. Can we have like a code block within new Strategy(){} like what you have mentioned... Sounds new to me... What does it mean? Do we override the class there? – rm -rf star Mar 9 '17 at 9:53
  • Now, why do non-overridden classes do not have implementations? This is because there are no anonymous classes needed. What does it mean? I couldn't get you here.... – rm -rf star Mar 9 '17 at 9:58
  • Also please explain me a bit more on 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).... I couldn't get you here :( – rm -rf star Mar 9 '17 at 10:05
  • 1
    Basically, if you have the {} block to override, it works like anonymous classes, otherwise just like normal new Object() calls. For information on anonymous classes, there are many guides online :) – SOFe Mar 10 '17 at 11:42
  • thanks @PEMapModder... Have understood that it works like anonymous classes and updated the same in an answer.. – rm -rf star Mar 10 '17 at 12:32
3

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.

  • Yes you are right @Michael Borgwardt. But when we call them as fields and when we call them as sub classes? – rm -rf star Mar 9 '17 at 8:25
  • Say for example when all the variables declared inside them are only fields then they would be the instance of the parent class or parent enum - this enum fields came into existence because - i can declare fixed set of constant values to reuse – rm -rf star Mar 9 '17 at 8:26
  • Similarly, why instances of subclasses` came into existence within an enum? – rm -rf star Mar 9 '17 at 8:27
  • @RajasubaSubramanian: The enum class has fields. The fields contain objects, and those objects are instances of (in this case) each a different subclass of the main enum class. It happens like that because that is how Java enums are implemented on the JVM. Enums are a feature of the Java language which was introduced in Java 5, but the JVM only knows about classes, so the Java compiler does this to make it look like there are enums. – Michael Borgwardt Mar 9 '17 at 8:53
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.