Enums: Properties vs. Methods

L

Lew

Daniele said:
If I were so inclined, I would argue that no, in the first case
"constant" is a noun, in the second an adjective, and that in the
clear-cut language of the JLS the noun 'constant' has a stringent
definition and the adjective 'constant', in the context of variables,
too, but that these definitions don't match.

What? This isn't about linguistics, this is about the fact that
constant variables are compiled as literal constants.

The notion of adjective and noun have no bearing on the technical
facts. Why would you bring that in?
But I won't, because I consider this whole issue a complete waste of
time, and only had responded to correct my inaccuracies, not to drive
any point.

Both constant variables and constants are compiled as constants. So
the difference is not any difference. BOTH are constants, no matter
how you look at the definition.

If you look into the bytecode and see the constant "false" (whatever
that is in bytecode), do you call that an adjective or a noun?
Because that's what's there in both examples.

BOTH are constants.
 
R

Robert Klemme

They're very different.  State is for implementing state machines.
Strategy is for extensibility.

The biggest difference, to me, is that if I were implementing a State
pattern, I'd treat the State class as an implementation detail and keep
it and its children private.  Whereas for Strategy having a public
Strategy interface/class is the whole point.

That does make sense. On a slightly different abstraction level (the
one I presented earlier) the difference boils down to when the
delegate is changed and probably also who it does (internally,
externally).

For me the crucial bit remains to delegate work to another instance
which may change - hence I'd say they are different but certainly not
_very_ different. After all these are *patterns* and not
*implementations* so there has to be some mental transformation done
during application anyway. I find it more productive to keep the
basic feature handy than to always explicitly remember whether it's
state or strategy.
 > Seehttps://gist.github.com/892503#file_valve.java

This really isn't either State or Strategy.  It's just an enum with some
properties.  I think you mean it to be a State, so let's start there.

I never claimed it was one or the other. State and Strategy were used
to describe the case where enum methods actually do something and not
just return constant properties.

Thanks for the healthy discussion!

Kind regards

robert
 
R

Robert Klemme

More the other way around: if it sees an opportunity to enregister
members it will remove the instance from the members.

Thanks for clarifying.
Yes.  So?  that's what HotSpot does, except it's not one per instance,
it's N >= 1 per instance, potentially.  HotSpot optimizes for
individual hot spots in the code, hence the name.

Hmm... Considering

public void hotSpotMethod(Valve v) {
// code
if (v.isOpen()) {
// ...
}
else {
// ...
}
// more code
}

Since this method can be invoked with different Valve instances the
only optimization I can see so far is

public void hotSpotMethod(Valve v) {
// code
if (v.open) {
// ...
}
else {
// ...
}
// more code
}

or are you saying that we can actually get this?

public void hotSpotMethod(boolean valve_open) {
// code
if (valve_open) {
// ...
}
else {
// ...
}
// more code
}
Yes, it wins, but that has nothing to do with memory or performance in
the JVM.

For the toy example given I would expect no difference, since the
final variables ocmpile to constants anyway.

But those final variables are only constant /per instance/. How would
hotspot be able to inline them?
THe use of values in a 'switch' doesn't seem relevant to the decision
between your approaches at all.

I never claimed this. This was just an explanation what the boolean
properties were intended for to help make the example better
understandable.
As for JVM effects, I would expect the two approaches to be
indistinguishable.  Constant variables are compiled into constants in
the code, so they get treated identically with constants (being, after
all, constants in truth) at run time.

I don't think these final members (which are not static!) can be
compiled into the code because there is just one class (and hence one
instance of each method) but multiple instances with different sets of
values for their final members.

Cheers

robert
 
R

Robert Klemme

The reason for my confusion:

I assume you refer to JLS v3.0.
 From the JLS, §17.5.3:

"If a final field is initialized to a compile-time constant ... uses of that
final field are replaced at compile time with the compile-time constant."

You left out an important part of the sentence:

"If a final field is initialized to a compile-time constant IN THE
FIELD DECLARATION, [...] uses of that final field are replaced at
compile time with the compile-time constant." (uppercase by me)
http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.5.3

This is not applicable in the "properties" case because final fields
are NOT initialized in the field declaration:

public enum Prop {

A(true, true), B(true, false), C(false, true);

private final boolean a;

private final boolean b;

Prop(boolean a, boolean b) {
this.a = a;
this.b = b;
}

// ...
}

Kind regards

robert
 
L

Lew

Robert said:
Hmm... Considering

public void hotSpotMethod(Valve v) {
// code
if (v.isOpen()) {
// ...
}
else {
// ...
}
// more code
}

Since this method can be invoked with different Valve instances the
only optimization I can see so far is

public void hotSpotMethod(Valve v) {
// code
if (v.open) {
// ...
}
else {
// ...
}
// more code
}

or are you saying that we can actually get this?

I make no claims whatsoever about individually crafted examples designed to
show where HotSpot might fail. I only repeat publicly available information
about what it does.
public void hotSpotMethod(boolean valve_open) {
// code
if (valve_open) {
// ...
}
else {
// ...
}
// more code
} ....
But those final variables are only constant /per instance/. How would
hotspot be able to inline them?

Per instance, or perhaps per call. Of course. It might then un-inline them
for a later call, then re-inline them - even the exact same call if conditions
change that affect optimization.

The beauty of HotSpot is that it accounts for changing run-time circumstances,
so it can perform optimizations that elude static analysis.

You should read about it.

....
I don't think these final members (which are not static!) can be
compiled into the code because there is just one class (and hence one
instance of each method) but multiple instances with different sets of
values for their final members.

The JLS requires them to be compiled into the code. And regardless of what
you don't think, that's exactly what happens. You should read about it.

Start here: JLS, §17.5.3, as I cited earlier.
 
L

Lew

Robert said:
You left out an important part of the sentence:

"If a final field is initialized to a compile-time constant IN THE
FIELD DECLARATION, [...] uses of that final field are replaced at
compile time with the compile-time constant." (uppercase by me)
http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.5.3

This is not applicable in the "properties" case because final fields
are NOT initialized in the field declaration:

public enum Prop {

A(true, true), B(true, false), C(false, true);

private final boolean a;

private final boolean b;

Prop(boolean a, boolean b) {
this.a = a;
this.b = b;
}

// ...
}

Excellent point.

And yet:

37: tableswitch { // 3 to 3
3: 67
default: 56
'3' is how it expanded 'kount' in the 'switch' in my example (where 'kount' is
final and set to 3).

and

public void run();
Code:
0: aload_0
1: getfield #21 // Field randy:Ljava/util/Random;
4: iconst_4
5: invokevirtual #30 // Method java/util/Random.nextInt:(I)I
8: istore_1

for
public void run()
{
int value = randy.nextInt( kount + 1 );

Note that the compiler DOES replace the reference with a constant. Looks like
I was right after all.
 
L

Lew

Note that the compiler DOES replace the reference with a constant. Looks like
I was right after all.
^^^^^

Wrong after all. Sorry. Wrong example presented. Please forgive.
 
R

Robert Klemme

I make no claims whatsoever about individually crafted examples designed to
show where HotSpot might fail.  I only repeat publicly available information
about what it does.

These examples were not crafted to show where HotSpot fails but to
learn what kind of optimizations you had in mind. I went from

http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html

and found

http://www.oracle.com/technetwork/java/whitepaper-135217.html#method
http://www.oracle.com/technetwork/java/whitepaper-135217.html#optimizations

which does not give away too much. There's also

http://en.wikipedia.org/wiki/Java_performance

But that did not provide too much insight either.

http://www.google.de/search?q=java+hotspot+optimizations

Wasn't too good either. What public resources did you have in mind?
Per instance, or perhaps per call.  Of course.  It might then un-inline them
for a later call, then re-inline them - even the exact same call if conditions
change that affect optimization.

Yes, but frankly, that's too general for me. Can you be more specific
with regard to the current case we are discussing?
The beauty of HotSpot is that it accounts for changing run-time circumstances,
so it can perform optimizations that elude static analysis.
Certainly.

You should read about it.

...


The JLS requires them to be compiled into the code.  And regardless of what
you don't think, that's exactly what happens.  You should read about it..

Start here:  JLS, §17.5.3, as I cited earlier.

It seems that is not a good place to start (see other postings). :)

Cheers

robert
 
L

Lew

@e21g2000yqe.googlegroups.com>, (e-mail address removed) says...

Quite frankly: Use what's easier to read and maintain.
Memory and runtime should be your smallest concern, assuming you use
some common sense when chosing your algorithm, only if there's clearly a
problem for the user and the system you should optimize to something
probably less readable. To find bottlenecks, don't guess, but use a
profiling tool. "jvisualvm" (which you can find in your jdk/bin folder)
is not bad for a start.


Like proposed elsewhere you could also write (untested):

public enum Prop {
//@formatter:eek:ff
A(){
public boolean isA(){return true;}
public boolean isB(){return true;}

},
B(){
public boolean isA(){return true;}
public boolean isB(){return false;}
},
C(){
public boolean isA(){return false;}
public boolean isB(){return true;}
}
;
//@formatter:eek:n

public abstract boolean isA();
public abstract boolean isB();
}


Consider that the use of boolean parameters is often quite bad to read
and maintain. Just have a look at your boolean initializer:

A(true, true), B(true, false), C(false, true);

You can't tell from looking at the code, whether the first argument
represents the return value for "isA" or "isB". From this point of view,
with a proper formatting, I'd prefer the abstract method approach.

I get your point about the parameter approach, but in an enum where everything
is together and nothing is public that is much less of a confusion. For that
I'd go with the first form for clarity and simplicity.
 
R

Robert Klemme

Do you mean how do we distinguish the two alternatives now?

I rather meant what is the assessment of the community about possible
optimizations applied by the JVM to both approaches? My personal
opinion at this point is that the "properties" approach might be more
efficient since getter methods can be inlined (there is just one class
so there are not multiple variants for e.isOpen() as opposed to having
different classes).

Cheers

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,834
Latest member
BuyCannaLabsCBD

Latest Threads

Top