Java trick

T

Thomas G. Marshall

Gary Labowitz coughed up:
"Thomas G. Marshall"


I guess I have to be more precise. At the point where we are talking
about this resolution issue the students haven't even gotten to
static modifier yet. So, I think what I am saying is correct for
them. However, your three point statement holds one area that I don't
like. "3. ... polymorphized object ..." gives me a problem. Since we
haven't covered static, and I think haven't covered overriding yet
mention of polymorphism isn't useful. So, I still want to default
back to my two statements, let them program a while and see the
results, and then we introduce other notions. The first being static,
the next being inheritance, and then overriding inherited methods to
achieve polymorphism. They are already familiar with "stuctural
polymorphism" due to overloading. Anyway, I'm still struggling to
find the perfect way to introduce all topics simultaneously -- maybe
just pass out the JLS and tell them to memorize it.

That'd be the wrong approach IMHO.

When I teach students, I'm similarly faced with being extremely careful in
my wording. I try to give examples that exploit one issue at a time. In
this case, I'd use something like my example program posted above, but
several incantations of it, slowly growing in size. Top only, then Top &
Bottom. Starting with members of objects, and then moving to statics. In
that order, only because of /this particular/ "overriding or not who belongs
to what" issue we're talking about.
 
T

Thomas G. Marshall

Gary Labowitz coughed up:
Lee Fesperman said:
Thomas said:
Lee Fesperman coughed up:
Thomas G. Marshall wrote:

Michael Borgwardt coughed up:
Thomas G. Marshall wrote:
The reason it works is that a variable to a class object of any
value can still yield access to a static.

Actually, there is no object involved at any point. The
*compiler*

[snip]

You're right. What I really should have said was a "variable of
reference of any value", not object.

Basically, given the declaration & definition:

{Type} {Variable Name} = {reference};

*Regardless* of the value of {reference},

{reference}.{static id}

yields the same thing as

{Type}.{static id}

It's simply a reference, you don't need a variable at all. It is
any expression producing a reference. It could be a method
returning a reference or even:

((Type) null).{static id}

The static can be a field or a method.

Your example is good, and it's one I've used before, except that
your explanation is missing how the thing is declared, which is why
it isn't about the reference.

The variable is declared with a type somewhere, or passed in as a
formal parameter of some type, etc. It is that type that
determines the static used, not the actual polymorphised object
underneath.

You completely missed my point. It is about the reference. A
variable is not necessary. There is no 'thing' declared. Try these:

I'm going to hit you with my semantic issue. There "sorta" is a
variable involved, but it is a "constant variable" over there in the
literal pool. And the constant variables in the literal pool have
type.

How's that for weaseling??

Criminey, I'm ashamed to admit that I love it. LOL.
 
T

Timo Kinnunen

If you need to change a static constant to an instance field in a way
that you didn't anticipate, there's a LOT of vetting of existing client
code that needs to happen anyway, and the compile errors would help you
considerably. Of course, if you did anticipate the change, then the
value wouldn't be a static field in the first place.

You get those compile errors simply by renaming the variable, so not
getting errors is not an argument for removing that feature.

Here's a usage I just thought up:

class Util1 { static void foo() {} }
class Util2 { static void bar() {} }
class Util3 { static void baz() {} }
class Main {
main() {
Util1.foo();
Util2.bar();
Util3.baz();
}
}

To move the static methods into Main, it could be changed to:

class Main {
static void foo() {}
static void bar() {}
static void baz() {}
static Main Util1, Util2, Util3;

main() {
Util1.foo();
Util2.bar();
Util3.baz();
}
}

I haven't had a chance to use this, but I find it pleasing in a perverse
way.
 
C

Chris Smith

Timo said:
I haven't had a chance to use this, but I find it pleasing in a perverse
way.

I, on the other hand, don't, and I'm suprised to hear that you do
(unless you mean that comment in a somewhat sarcastic way). In fact,
this seems like so obviously a very bad idea that I would seriously
question the wisdom of leaving someone employed after they pull a stunt
like this. If a couple people have been allowed to do things like this
over an extended period of time, it may well be time to scrap the
project and rewrite from scratch.

Competent software people do sustainable work. That's the bottom line.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Thomas G. Marshall

Chris Smith coughed up:
I, on the other hand, don't, and I'm suprised to hear that you do
(unless you mean that comment in a somewhat sarcastic way).

The way he phrased this makes it very clear to me that
/of course/ he was being sarcastic.

....[rip]...

--
Iamamanofconstantsorrow,I'veseentroubleallmyday.Ibidfarewelltoold
Kentucky,TheplacewhereIwasbornandraised.ForsixlongyearsI'vebeenin
trouble,NopleasureshereonearthIfound.ForinthisworldI'mboundtoramble,
Ihavenofriendstohelpmenow....MaybeyourfriendsthinkI'mjustastrangerMyface,
you'llneverseenomore.ButthereisonepromisethatisgivenI'llmeetyouonGod's
goldenshore.
 
L

Lee Fesperman

Thomas said:
Lee Fesperman coughed up:

To me, when someone says "it's about the reference", they are in effect
saying that it's about the object that that references points to, since
that's what a reference does.

No wonder you're confused. It's not about variables or declarations or about objects
(since the reference could be null). It's about the type of the reference or better, the
reference expression. The general form is

{reference expression}.{static member}

The compiler uses the type of the reference expression to determine which
class/interface to find the static member in.
 
L

Lee Fesperman

Gary said:
I'm going to hit you with my semantic issue. There "sorta" is a variable
involved, but it is a "constant variable" over there in the literal pool.
And the constant variables in the literal pool have type.

How's that for weaseling??

In my view, a string literal is different from a variable in the Java Language; the fact
that it could be considered a constant variable because of the literal pool is an
implementaion detail. However, I will accept your 'weasel' (I half expected such a
challenge but kept the example in because it was cute) since it only requires removing
one of my 4 examples:

"".valueOf("*");

.... my point is still intact with the other 3 examples ;^) BTW, all of my examples have
type; they have to!
 
C

Chris Smith

Thomas said:
The way he phrased this makes it very clear to me that
/of course/ he was being sarcastic.

Okay, I didn't get that clearly, but that's why I added the
parenthetical comment.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Timo Kinnunen

I, on the other hand, don't, and I'm suprised to hear that you do
(unless you mean that comment in a somewhat sarcastic way).

Yes, it's that the variable is used to convey one type to the compiler and
a different type to the reader, all the while hiding that this reviled
feature is used.

Interestingly, if the SomeClass.someStaticMethod() syntax was not allowed,
this technique could be used to fake it.
In fact,
this seems like so obviously a very bad idea that I would seriously
question the wisdom of leaving someone employed after they pull a stunt
like this. If a couple people have been allowed to do things like this
over an extended period of time, it may well be time to scrap the
project and rewrite from scratch.

Of course you don't do such a change willy-nilly, but if you have a size
constraint and you can't cut functionality, I don't see much choice other
than getting rid of everything that isn't needed, including cutting classes
that do nothing more than group together related methods.
Competent software people do sustainable work. That's the bottom line.

But that's the point, to sustain the conseptual divide between Util1.foo(),
Util2.bar() and Util3.baz() in the face of them moving to a single class.
You could rename them to util1_foo(), util2_bar() and util3_baz() and
retain most of the original design, but this way you don't have to change
every call-site and you don't (necessarily) need ugly prefixes, even though
they are a good idea.

Perhaps an extended example makes the advantage clearer. Util1, 2 and 3 as
before. Starting point:

class Main { main() { Util1.foo(); Util2.bar(); }}
class Other { other() { Util2.bar(); Util3.baz(); }}

Option 1: Move utility methods to Main using prefixes:

class Main {
// prefixed foo(), bar(), baz()
main() {
util1_foo();
util2_bar();
}
}

class Other {
other() {
Main.util2_bar();
Main.util3_baz();
}
}

Option 2: Move methods and introduce variables for them to be used thru:

class Main {
// normal foo(), bar(), baz()
// variables for Util1, Util2, Util3
main() {
Util1.foo();
Util2.bar();
}
}

class Other {
// variables for Util1, Util2, Util3
other() {
Util2.bar();
Util3.baz();
}
}

In option 1, the main() method stayed relatively stable, but the other()
method was altered greatly. In option 2, both main() and other() remained
as they were. Any meaning that the Util1 class name conveyed before is
still conveyed in full.
 
C

Chris Smith

Timo said:
Of course you don't do such a change willy-nilly, but if you have a size
constraint and you can't cut functionality, I don't see much choice other
than getting rid of everything that isn't needed, including cutting classes
that do nothing more than group together related methods.

That much is potentially reasonable. The "trick" to accomplish this is
not.
But that's the point, to sustain the conseptual divide between Util1.foo(),
Util2.bar() and Util3.baz() in the face of them moving to a single class.

Oh, come on. It's fairly obvious that we're not talking about the same
thing. I meant that competent developers adopt software development
techniques that do not kill their projects. I don't mean that they
preserve surface textual similarities that no longer really apply.
You could rename them to util1_foo(), util2_bar() and util3_baz() and
retain most of the original design, but this way you don't have to change
every call-site and you don't (necessarily) need ugly prefixes, even though
they are a good idea.

util1_foo is better than declaring a faux variable that looks like a
class name so that you can pretend you're still calling a method in a
class that really no longer exists. It's no poorer in maintaining a
"conceptual distinction". It's probably easier to do, assuming you have
a fairly average tool set, than adding a set of false variable
declarations to every class in the project that uses the utility methods
In option 2, both main() and other() remained
as they were.

No, they didn't. This reminds me of the anecdote about the Chevy Nova
-- that when it was sold in Spanish-speaking countries they uised the
same name, despite that it means "doesn't go" in Spanish. Perhaps
Chevy's marketing people protested, "It's the same name as we used in
the United States; why make a change?"

You may be making the code *look* the same, but a quarter of an inch
below the surface, it's radically different, not to mention misleading.
If you think that future programmers will never need to look down that
quarter of an inch, I think you're building a house of cards, and it's
bound to collapse on you.

So the lesson: get a decent editor with refactorings, or a regular
expression search and replace utility, and do it right.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Timo Kinnunen

Oh, come on. It's fairly obvious that we're not talking about the same
thing. I meant that competent developers adopt software development
techniques that do not kill their projects. I don't mean that they
preserve surface textual similarities that no longer really apply.

They might want to, if they have a development branch which has no size
constraints.
util1_foo is better than declaring a faux variable that looks like a
class name so that you can pretend you're still calling a method in a
class that really no longer exists. It's no poorer in maintaining a
"conceptual distinction".

I'd say ScreenUtilities.displayProgressBar() is clear and
ConnectionUtilities.screenUtilities_displayProgressBar() is confusing.
It's probably easier to do, assuming you have
a fairly average tool set, than adding a set of false variable
declarations to every class in the project that uses the utility methods

Perhaps, but who says you can't have really great tool to support this
trick?
No, they didn't. This reminds me of the anecdote about the Chevy Nova
-- that when it was sold in Spanish-speaking countries they uised the
same name, despite that it means "doesn't go" in Spanish. Perhaps
Chevy's marketing people protested, "It's the same name as we used in
the United States; why make a change?"

Sorry, but that story, while notable, is not true:
http://www.snopes.com/business/misxlate/nova.asp
You may be making the code *look* the same, but a quarter of an inch
below the surface, it's radically different, not to mention misleading.
If you think that future programmers will never need to look down that
quarter of an inch, I think you're building a house of cards, and it's
bound to collapse on you.

Like I said, I haven't tried it in practise. I do know that it isn't the
real thing. It has a different set of advantages and disadvantages than
prefixes. I don't like that it doesn't prevent me from mixing the variables
and writing total gibberish. But I might still give it a shot; it isn't
like it can't be quickly removed even with less than average tools.
So the lesson: get a decent editor with refactorings, or a regular
expression search and replace utility, and do it right.

But the motivation for the change is optimization. There is no right thing
to do, there are just varying degrees of wrongness.
 
C

Chris Smith

Just a few more words.

Timo said:
I'd say ScreenUtilities.displayProgressBar() is clear and
ConnectionUtilities.screenUtilities_displayProgressBar() is confusing.

Yes, that's exactly the problem. If the first expression were less
"clear" in its lies, there wouldn't be such a problem, because later
programmers would have to check their assumptions and discover that the
code is lying to them.

Since in all of the examples in this thread there are really suspicious
variable declarations at the beginning of each class, it's conceivable
that a maintenance programmer might only waste an hour or so trying to
figure out this clever trick, or less if the class is rather simple. I
really hope no one adopts this and then decides to combine it with an
inherited public field in a widely used base class. That could cost the
maintenance programmer most of a day.
Perhaps, but who says you can't have really great tool to support this
trick?

No such tool exists. I'm feeling fairly confident in saying so, because
despite not having examined every possible such tool, I know that anyone
who created such a tool would be the subject of such hilarity and/or
outrage that we probably would have caught wind of it on the newsgroup
here.

I share your dislike for the method name prefixes, but that pales in
comparison with the monstrous idiocy that characterizes this kind of
confusion. (And I don't think the scenario is very believable in the
first place; devices where one extra class file overhead makes a
difference aren't being written in bytecode-compiled Java. Native
compilers can address this issue and use no less space in multiple
classes than in only one.)

Anyway, enough. People will make up their own minds.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
P

P.Hill

Timo said:
But the motivation for the change is optimization.

If the motivation is optimization, you DONT want to
be making extra objects just so you cna jump through them.
Static dispatch is always faster than dynamic.
There is no right thing
to do, there are just varying degrees of wrongness.

But you'd better stick to your own criteria then.

-Paul
 
P

P.Hill

Thomas said:
When I teach students, I'm similarly faced with being extremely careful in
my wording.

When you say the following, you have the usage of "type" and "class"
exactly reversed, as Joona said:
Objects have class. References have type.
No, you're wrong, and you've made it even more confusing.

1. Static data OR METHODS are referred to based upon the /declaration/ of
the Class (of the reference variable for example).

1. Static data OR METHODS are referred to based upon the declaration of
reference variable (the class name mentioned in the declaration). This is not
just an example this is how it works, there are no other cases.
2. Non static data are ALSO referred to based upon the declaration of the
Class.

2. Non static data OR METHODs are referred to based upon the class of the
underlying object. (the name used in the class declaration).
3. Non static methods are referred to based upon the type of the
polymorphized object underneath.

-Paul
 
T

Thomas G. Marshall

P.Hill coughed up:

....[rip]...
of the > Class.

2. Non static data OR METHODs are referred to based upon the class of
the underlying object. (the name used in the class declaration).


/NO/, you *still* have it wrong.

The non static data is /not/ referred to based upon the class of the
underlying object.

In the example I posted, the (Top).nonstaticstring was accessed from a
Bottom underlying object instance, because the variable was declared as Top.

Look at the run results again:

$ run experiments.simple.StaticPolyAccess
Top static string
Top static method
*Top non static string* <---------------------
Bottom nonstatic method

And this is the source:

<SOURCE>
package experiments.simple;

class Top
{
static String staticstring = "Top static string";
static void staticmethod() {System.out.println("Top static method");}
String nonstaticstring = "Top non static string";
void nonstaticmethod() {System.out.println("Top nonstatic method");}
}

class Bottom extends Top
{
static String staticstring = "Bottom static string";
static void staticmethod() {System.out.println("Bottom static method");}
String nonstaticstring = "Bottom non static string";
void nonstaticmethod() {System.out.println("Bottom nonstatic method");}
}

public class StaticPolyAccess
{
public static void main(String[] args)
{
Top bottom = new Bottom();
System.out.println(bottom.staticstring);
bottom.staticmethod();
System.out.println(bottom.nonstaticstring);
bottom.nonstaticmethod();
}
}
</SOURCE>


....[rip]...
 
P

P.Hill

Thomas said:
/NO/, you *still* have it wrong.

The non static data is /not/ referred to based upon the class of the
underlying object.

Well, at least I have the terms type and class correct now. :)
$ run experiments.simple.StaticPolyAccess
Top static string
Top static method
*Top non static string* <---------------------

That is the result of 'hiding' NOT polymorphism.
In the member (or virtual if you're an old C++ person) methods case
the Bottom.nonstaticmethod() polymorphically overrides the
Top.nonstaticmethod() while in the member variable case there
are actually two strings accessable from the variable bottom.
The resolution of which of these strings to access IS based on type
of the reference variable.

I hope your not teaching anything that includes the use of
two member variables by the same name in one (sub)class.

If we change the main to:
Top bottom = new Bottom();
System.out.println(bottom.staticstring);
bottom.staticmethod();
System.out.println(bottom.nonstaticstring);
System.out.println(((Bottom)bottom).nonstaticstring);
bottom.nonstaticmethod();

results in:
Top static string
Top static method
Top non static string
Bottom non static string
Bottom nonstatic method

We can see that two nonstaticstrings in one object.
Do us all a favor and don't even go there, or if you do always say
"This is probably not what you want to do, 'cause it's confusing and
will lead to bugs."
And while you're at it learn to say "member method" and "member
variable" in an OO and JLS kind of way instead of nonstatic.

-Paul
 
T

Thomas G. Marshall

P.Hill coughed up:

(snipped out by P.Hill):

P.Hill:
2. Non static data OR METHODs are referred to based upon the class of
the underlying object. (the name used in the class declaration).



Well, at least I have the terms type and class correct now. :)


That is the result of 'hiding' NOT polymorphism.

No kididng, I didn't SAY this access was polymorphism. If it /was/
polymorphism and data elements could be overridden, it would have reffered
to the member element of the Bottom instance.

You said:
Non static data OR METHODs are referred to
based upon the class of the underlying object.

The data members are not, as shown. In my example, the class of the
underlying object is Bottom. Non-static data are not referred to based upon
the class of the underlying object. In my example, the non-static data is
clearly from Top.
 
T

Timo Kinnunen

On Mon, 20 Sep 2004 12:21:14 -0600, Chris Smith wrote:

I'll just comment on this.
(And I don't think the scenario is very believable in the
first place; devices where one extra class file overhead makes a
difference aren't being written in bytecode-compiled Java. Native
compilers can address this issue and use no less space in multiple
classes than in only one.)

One class is not a problem, that's true. 400Kb of normal class files into a
64Kb jar-file, that's a problem. It is doable, but it isn't painless and
it's not pretty. Native compilation is right out of the question due to
security conserns. It's J2ME on mobile phones.
 

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,774
Messages
2,569,599
Members
45,172
Latest member
NFTPRrAgenncy
Top