• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Enums (super call)

 
Jonathan Storey
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
While reading my JSCP book, I starting playing about with enums. I wonder if anyone is able to answer this question.

//*****CODE SAMPLE********

class Coffee3 {

enum CoffeeSize3
{
BIG(2){public int getOunces(){return super.ounces()*3;}},
SMALL(1);


CoffeeSize3(int ounces)
{
this.ounces = ounces;
}

public int getOunces()
{
return ounces;
}


public void setOunces(int ounces)
{
this.ounces = ounces;
}

private int ounces;
}


CoffeeSize3 size;
}

public class TestEnums3
{
public static void main (String[] args)
{
Coffee3 drink3 = new Coffee3();
drink3.size = Coffee3.CoffeeSize3.BIG;
//size = Coffee3.CoffeeSize3.BIG;

System.out.println(drink3.size.getOunces());
Coffee3.CoffeeSize3.BIG.setOunces(10);
//Coffee3.CoffeeSize3.BIG.ounces =22;
System.out.println(drink3.size.getOunces());
}
}


//******END CODE

Can someone explain to me why if I set the overriden 'getOunces()' method to be

BIG(2){public int getOunces(){return ounces()*3;}},

removing the 'super' call on that method the compiler complains with the error

Exception in thread "main" java.lang.NullPointerException
at TestEnums3.main(TestEnums3.java:40)

And my eclipse session adds

Multiple markers at this line
- overrides Coffee3.CoffeeSize3.getOunces
- Cannot make a static reference to the non-static field ounces

But leaving in the super call on that variable returns the value I expected? Surely 'super' calls are reserved for sub/super classes?

Thanks,
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't see where you define the ounces() method.

When you add a body to an enum constant, you create an anonymous subclass of the enum type. That is why super is appropriate.
 
Jonathan Storey
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, the brackets where left in by error. The code should have been

BIG(2){public int getOunces(){return super.ounces*3;}},


The question is really, why if I do the above does the code work as expected but if I leave off the 'super' part, I get an error 'non-static variable ounces cannot be referenced from a static context' and why adding 'super' resolves this issue?
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My question is: why does super.ounces *not* raise a compile time error? After all, ounces is private, and therefore shouldn't be accessible through the super reference.

It might actually be a bug in the Eclipse compiler. Did you try to compile the same with the Sun compiler? What version of Eclipse are you using?
 
Jonathan Storey
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
We tried it from a command prompt using Java 1.6 compiler on Linux and we got the same error?

Eclipse SDK Version: 3.2.0 running JDK 1.5.07
[ May 15, 2007: Message edited by: Jonathan Storey ]
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've tested this with Sun's JDK 1.5.0_11, and it also works.

The Java Language Specification doesn't say a lot about constant-specific class bodies because they state that they think the use will be rare.

Consider this example.



If you examine the bytecode produced when Judges is compiled, you see the following methods.



Notice that special method called access$102.

It appears that this method is what is used to actually change the value of the variables in the enum type.

Look at the bytecode produced from one of the constant bodies.



It appears that there is a special treatment of the keyword super here to access variables and methods in the enum type.

Note that if you try to just use the keyword super by itself within the constant-specific class body, you get a compile-time error, whereas in a normal class definition, super can be used by itself.

As an example, if I change the first constant-specific class body to

,

I get the following syntax error.


[ May 15, 2007: Message edited by: Keith Lynn ]
 
Bupjae Lee
Ranch Hand
Posts: 107
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, 'specialized enum constants' is implemented by anonymous local class declared in static initializer ( i.e static{} ).

If you omit super in super.ounces, compiler treats it like this:



Although anonymous class has its own ounces field, compiler interpretes as CoffeeSize3.this.ounces, and complains about that: you use instance field in static method.
[ May 15, 2007: Message edited by: Bupjae Lee ]
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic