I personally like generics and inner classes have their purpose.
If the problems to be solved get more complex a language is suitable
to solve them if it requires the leas effort. From my point of view it
just simplified it further.
Why isn't assembly the simplest language? It has a handfull of
features only. The more features, the higher the level a language
gets.
Regards,
I agree entirely.
Evolving a language is a Good Thing, but it should evolve in the direction of
greater generality, power, and expressiveness -- not into a grab-bag of random
hacks and half-baked features.
I used to like Java a lot. I still retain some fondness for it, but I dislike
it more and more with each major release. It's reached the point where,
although I'm perfectly content to use Java if someone is paying me for it, I'm
very unlikely to choose Java for any of my personal projects.
-- chris
impaler wrote:
> I personally like generics and inner classes have their purpose.
> If the problems to be solved get more complex a language is suitable
> to solve them if it requires the leas effort. From my point of view it
> just simplified it further.
Obviously the OP does not understand inner classes, which have been around
since the beginning and exist in other languages. Among other things they
provide a sort of "poor-man's" closure mechanism. (Yes, I know it isn't up to
everything closures can do, but it is up to everything I've needed in practice.)
The OP also seems to think that generics have reduced the value of Java, where
most seem to think they have enhanced it.
Most people in my observation that are "frustrated" with one or another Java
feature don't understand it, are simply trolling, or both. There are assuredly
aspects of Java that could have been done better, but come on, citing generics
and inner classes as declines in the language?
Come to think of it, lots of people think generics could have been done
better. Of course, most of their ideas would have broken backward
compatibility; the current mechanism is a compromise. Still, generics
represents an improvement over Java 1.4 and earlier.
I see the future holding enhancements to Java that will help workaday
programmers build practical enterprise-scale, robust, maintainable systems
more effectively, while others will undoubtedly whine about this or that
putative theoretical or stylistic shortcoming.
It's all FORTRAN to me anyway.
- Lew
>
> I used to like Java a lot. I still retain some fondness for it, but I dislike
> it more and more with each major release. It's reached the point where,
> although I'm perfectly content to use Java if someone is paying me for it, I'm
> very unlikely to choose Java for any of my personal projects.
>
> -- chris
>
>
Out of curiosity: what language do you use, Chris?
(Every language has its star-burst, formative period, with fanatical
screaming and shouting from proponents; every two years or so something
detonates and spews astronomical amounts of radiation all over the other
languages jostling for position in the firmament; but if you filter all
that out, and listen really, really hard, you'll hear the faint but
constant droning that everything's heading in one direction: Lisp. I
took a peek at a Lisp program the other day and didn't understand a
word, expression, or open square bracket of it. The programming universe
is a strange place.)
.ed
--
www.EdmundKirwan.com - Home of The Fractal Class Composition.
Download Fractality, free Java code analyzer:
www.EdmundKirwan.com/servlet/fractal/frac-page130.html
> if you filter all
> that out, and listen really, really hard, you'll hear the faint but
> constant droning that everything's heading in one direction: Lisp.
Scheme isn't.
Try taking the cdr of that program recursively until you reach the
atom at its center....
....cuz if you list the pros and cons, defun of Lisp is in peeling the
onion until you have nil...
....at that it will seem as simple as driving a car....
And incidentally, if Lisp is the future, then it's like Deja Vu all
over again....
Scheme's already a Lisp derivation, is it not?
Generics is controversial enough that I'd hesitate to use the word
"most". Certainly, *I* think Java 1.5 is better than 1.4... but I'm not sure
if *most* people do.
[...]
>
> Come to think of it, lots of people think generics could have been done
> better. Of course, most of their ideas would have broken backward
> compatibility; the current mechanism is a compromise. Still, generics
> represents an improvement over Java 1.4 and earlier.
Right. Generics was a good idea, but its implementation (type erasure)
was poor. As for the backwards compatibility thing, I might have been
sympathetic at the time, but apparently the 1.6 class file format is not
backwards compatible with the 1.4 format (and Java 1.5 used the 1.4 format),
and as far as I can see, 1.6 didn't add any really big new features over
1.5. So what gives?
- Oliver
> Out of curiosity: what language do you use, Chris?
Smalltalk, when I can. Which I discovered after I'd been programming Java for
a couple of years (around the time of JDK 1.2 as I recall).
> (Every language has its star-burst, formative period, with fanatical
> screaming and shouting from proponents; every two years or so something
> detonates and spews astronomical amounts of radiation all over the other
> languages jostling for position in the firmament; but if you filter all
> that out, and listen really, really hard, you'll hear the faint but
> constant droning that everything's heading in one direction: Lisp.
;-)
I've never really got the hang of Lisp. I've played with it a bit, on and off,
as I've played with many languages, but I don't feel tempted to put a lot more
effort into becoming fluent. Each time I've tried it, I've been put off by the
quality of the support tools, the (to my eyes) labyrinthine complexities of the
Common Lisp libraries, and the nasty historical hangovers (true is 't, but
false is () ? False is a kind of list ?? OK, polymorphism, right, but...)
I can understand the Lispers' viewpoint that it subsumes /everything/, but I
don't fully agree, and I certainly don't agree that it subsumes most things
/well/.
-- chris
> When Java first become popular I remember it being touted as having
> all the nice features of C++ without any of the ugly bits.
As a C programmer at heart, it hurts to hear all those lovely C-isms
which still litter C++ referred to as "ugly bits" ;-)
> However as
> time goes it seems to be gettiing more and more complicated.
Beauty is in the eye of the beholder, but I think generics actually
made Java look much more becoming. Inner classes are another story...
As with many things, just because a language *allows* you to use
certain constructs doesn't mean you *should*.
--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
I agree un-entirely.
Specifically, I object to the complaints about inner classes. I remain
convinced that inner classes are one of the most important advances in
OO C-family languages that have come about for some time. They are very
nearly as liberating for objects as lambda expressions are for
functions; things that are very neatly expressed with them are
simultaneously very clumsy without them.
That said, there are things about Java that seem less than appealing in
that they introduce new syntax for little or no reason. Some of them
were present in the original language (e.g., the access specifiers
copied from C++), and some were added later (generics, generics, and ...
oh yeah, I almost forgot generics).
--
Chris Smith
I think this is misleading as it applies to Java. There was certainly a
fair degree of excitement and hype around the initial release; but a
large number of people also have legitimate reasons for a change in
opinion; the language has changed. We've reached the "too many cooks"
point. This time, the language itself wasn't designed by committee, but
the evolution since then certainly was.
In retrospect, the best thing for Java would have been if Sun had never
set up the Bug Parade. I'll admit that I'm not innocent; I thought it
was great! I set up a web page listing my proposals for adding to the
language. The problem is that I thought I knew everything; and now, a
mere six years later, it is clear to me that I didn't. But lots of
other people who lacked the same knowledge as I were able to vote for
their favorite features in the Bug Parade... and then Sun decided to
respond to community input. What a way to kill something that used to
be elegant and simple!
> but if you filter all
> that out, and listen really, really hard, you'll hear the faint but
> constant droning that everything's heading in one direction: Lisp.
Whatever. Or at least so certain people would love for you believe.
In reality, Lisp is a rather poor *language* that embodies some very
good *ideas*. Ultimately its insistence, and the insistence of its
advocates, that the rest of the world should change to fit LISP is
ridiculous. It's amazing to me what passes for good sense in some
programming language communities.
--
Chris Smith
> Specifically, I object to the complaints about inner classes. I remain
> convinced that inner classes are one of the most important advances in
> OO C-family languages that have come about for some time.
IMO the /concept/ is OK, on average, but the implementation is less so. Or
rather, of the three different, and only somewhat related, sorts of nested
class, I think:
Static member classes. Concept is fine -- excellent in fact (not at all new,
but that's no shame). Slightly worried about the semantics with respect to
inheritance of/by member classes (which has been a longtime source of bugs in
the compiler -- indicating, to my mind, that this is more of a minefield than
it looks). More worried by the implementation of backdoor access to members.
Roughly as worried by the implementation of "protected" and "private" member
classes. I /really/ don't like all those extra methods and other hackery.
Non-static member classes. Concept OK, I don't see much benefit in extending
the static concept by having an automatically supplied reference to the outer
object, but it's not that big a deal. Complaints and worries, as for static
member classes, plus a dislike of the hackery needed to pass the outer
references to the member classes' constructors.
Inner classes (I hope I'm getting the terminology correct). There is a really
great concept there, but unfortunately they didn't choose to implement that
concept. Instead they choose to hamstring the idea by not allowing full access
to the local variables of the surrounding method. Dislikes: as for static
member classes plus:
+ The anonymous class syntax is a disgrace.
+ Given the hamstrung access to the outer variables, I think it would
have been better to have used a syntax to make it clear that the inner
class instance copies their values as it is constructed, rather than
constrain the outer variables.
And is there really that much benefit in inner classes over the classic closure
concept ? I'm not sure, though I'd be willing to argue the case either way.
Someday I must scan rt.jar to see how many inner classes implement more than
one method.
> They are very
> nearly as liberating for objects as lambda expressions are for
> functions; things that are very neatly expressed with them are
> simultaneously very clumsy without them.
The aim was laudable, I agree. I don't like what they actually achieved nearly
as much.
-- chris
Another endless discussion, just like the threads:
- Why does Java require the throws clause? Good or bad language
design?
- Java needs "goto"
- Help me!! Why java is so popular
Ah, yes. I confess to jumping from "inner classes" to "anonymous inner
classes". Nested classes are fine; probably ought to be expected.
Nothing revolutionary. Named inner classes are clumsy, honestly, and I
never use them. It is anonymous inner classes that I find quite
revolutionary among mainstream OO languages.
> Inner classes (I hope I'm getting the terminology correct). There is a really
> great concept there, but unfortunately they didn't choose to implement that
> concept. Instead they choose to hamstring the idea by not allowing full access
> to the local variables of the surrounding method.
I would like to see that decision reversed as well. Ultimately, though,
I don't think it's the main benefit of anonymous inner classes. The
revolutionary idea is that your choice of building abstractions no
longer has to follow the structural needs of code in terms of
implementing interfaces and such. The general idea of decoupling those
was pretty unprecedented among mainstream OO languages. As useful as it
would have been to be able to access local variables as well, that would
have merely added an implementation technique; it doesn't extend into
the design sphere.
> + The anonymous class syntax is a disgrace.
Is there something you'd prefer?
> + Given the hamstrung access to the outer variables, I think it would
> have been better to have used a syntax to make it clear that the inner
> class instance copies their values as it is constructed, rather than
> constrain the outer variables.
Why? That's not required; it's simply a logical implementation
decision. The current syntax opens the door to removing that
restriction in the future without having some clumsy field-copying
syntax left lying about.
> And is there really that much benefit in inner classes over the classic closure
> concept ? I'm not sure, though I'd be willing to argue the case either way.
> Someday I must scan rt.jar to see how many inner classes implement more than
> one method.
Given that Java lacks first-class functions, I'd say it would have
complicated the language more to add them instead of anonymous classes.
Like it or not, classes are basically the only significant unit of
abstraction in Java; and that is part of its simplicity. As much as I
like languages with first-class functions, I don't know that I'd be
certain they are a good thing to add to Java. At a certain point, one
needs to let a language have its character, and pick a different
language if one wants a different character.
--
Chris Smith
This is the use of anonymous classes which would be solved equally well by
method pointers, which are conceptually much simpler (or at least more
familiar from other C-base languages.) I find Sun's white paper extolling
the virtues of anonymous classes over method pointers quite unconvincing.
More familiar yes, but not conceptually simpler. I think anonymous
classes are rather simpler in concept than method pointers in C++.
Mark Thornton
I disagree, and that gets us nowhere, does it? :-)
Assume we're introducing only the bound method pointer, that is, an object
that:
o - is typed just as a method is, with a specific "this" type, argument
types, and return type.
o - when created, is bound to a "this" object and a method name
o - does only one thing after being created -- call the method it was bound
to
I submit that, to anyone familiar with OO (in particular, dispatch of
virtual functions), the idea of an object that encapsulates a method call is
an obvious one. I submit further that there are no bothersome subtleties
here. Having written one test program that used these method pointers,
you'll know exactly how they work, and the answers to whatever questions
might be raised are obvious.
Q: What if the object gets collected?
A. The method pointer references it, so it can't be collected wile the
pointer's still live.
Q. What thread does the called method run on?
A. The same thread as the caller, like any other method.
Q. How many times can I use a single method pointer?
A. As many times as you like, just as you could call the method directly as
many times as you like.
Anonymous classes are, I submit a bit more complex. Yes, they're classes,
and that answers a lot of questions about them. But their access to the
private parts of their enclosing class (necessary, if they're going to be
useful callback handlers) introduces more complicated and somewhat arbitrary
behavior:
Q. But what use are they if they can only invoke public behavior on their
enclosing class?
A. Exactly. That's why they can access private parts of their enclosing
class too. And their enclosing classes can access their private parts too.
Q. Why that last part?
A. Umm, symmetry. And they can access final members of the block that
creates them.
Q. You mean, scalars and strings, that are truly constant?
A. No, objects too. Including mutable ones.
Q. So the anonymous class can access an object that might change out from
under it, but not an object *reference* that might change out from under it?
A. Exactly.
Q. And I can define static members of the anonymous class, to define
properties that all of the instances will have in common?
A. No.
Q. Why not?
A. Because. But you *can* define them as statics on the containing class,
further away from where they're used, and with nothing syntactic to indicate
that they're intended as part of the anonymous class.
Q. OK, I feel better. But it seems to me that the purpose of the
anonymous class is to make its methods as much as possible like methods of
its enclosing class, while allowing them to be run from a wider selection of
callers, for instance, via callback interfaces the enclosing class doesn't
implement.
A. Exactly.
Q. Then why not have a mechanism where the method *can* be part of the
enclosing class, and be called via something other than its name?
A. Because that would be complicated.
> Q. Why not?
> A. Because. But you *can* define them as statics on the containing class,
> further away from where they're used, and with nothing syntactic to indicate
> that they're intended as part of the anonymous class.
It may have been simply to simplify the implementation of Java. Inner classes
are tied to the enclosing instance. Making static members visible only to
instances created within the enclosing object, but not to other objects of the
enclosing class, would have been difficult to implement and conceptually
difficult for many workaday programmers. Far simppler to allow only final
constant members to be static, as inner classes do, which renders moot the
question of visibility betweendifferent enclosing instances.
It occurs to me that many things left out of Java might seem very useful to
highly skilled programmers for certain corner applications, but that the
compromises may make life simpler for the gazillions of journeyman programmers
who do not have quite that deep a grasp on computer science. I do not know if
this is what Sun had in mind, and may not be enough to justify the
compromises, but it seems to make sense.
- Lew
I don't know what you mean by "instances created within the enclosing
object". Static fields of an inner class would, logically, act exactly like
static fields of any other class: accessible as fully-qualified name to any
code that is allowed to access them, and as simple names within the class
itself. (For anonymous and local classes, which have no fully-qualified
names, only visible within the class.) This wouldn't be difficult to
implement; in fact, I suspect all that would be necessary is removing the
current checks that make non-constant static members illegal.
The current restrictions limit the complexity of the code run while
initializing an inner class; I don't see any particular need for that.
Not true. Inner classes belong to an instance of the enclosing class.
So, for example, (untested)
public class Foo
{
class Bar
{
}
public static void main( String [] args )
{
Foo a;
Foo b;
}
}
In this example, a.Bar and b.Bar are /different/ classes. They cannot share
static non-constant members.
- Lew
No, inner class *instances* have an enclosing *instance*.
>
> So, for example, (untested)
>
> public class Foo
> {
> class Bar
> {
> }
>
> public static void main( String [] args )
> {
> Foo a;
> Foo b;
> }
> }
>
> In this example, a.Bar and b.Bar are /different/ classes. They cannot
> share static non-constant members.
There's only one class; it's called Foo$Bar. Try running the following
program:
public class Foo
{
class Bar
{
}
public static void main( String [] args )
{
Foo a = new Foo();
Foo b = new Foo();
Bar ab = a.new Bar();
Bar bb = b.new Bar();
System.out.println(ab.getClass());
System.out.println(bb.getClass());
System.out.println(ab.getClass() == bb.getClass());
}
}
Mike Schilling wrote:
> No, inner class *instances* have an enclosing *instance*.
>> So, for example, (untested)
>>
>> public class Foo
>> {
>> class Bar
>> {
>> }
>>
>> public static void main( String [] args )
>> {
>> Foo a;
>> Foo b;
>> }
>> }
>>
>> In this example, a.Bar and b.Bar are /different/ classes. They cannot
>> share static non-constant members.
> There's only one class; it's called Foo$Bar. Try running the following
> program:
Interesting, because in the section (8.1.3) on inner classes the JLS states
"So, for example, the class Local above has an enclosing instance of class
Outer. "
So while the actual implementation may use a single class definition, it has
to act as if each instance has its own Local class.
- Lew
You're being misled by sloppy wording. It should say "Every instance of
class Local ...". Note that the definitions at the start of 8.1.3 include
the definition of an enclosing class of an inner class and the definition of
an enclosing instance of an inner class instance, but not the definition of
an enclosing instance of an inner class, becasue there is no such thing.
Note also the following paragraph, which is more careful with its language:
"Here, every instance of WithDeepNesting.Nested.DeeplyNested has an
enclosing instance of class WithDeepNesting.Nested (its immediately
enclosing instance) and an enclosing instance of class WithDeepNesting (its
2nd lexically enclosing instance)"
Since Foo$Bar is byte code, it is not a reliable indicator of what the Java
language is. That is why I went to the JLS for my insight.
The Java language is what's enforced by the compiler; Foo$Bar is what the
compiler produces after the syntax is approved, and is no longer Java.
Not only is Foo$Bar not associated with any instance, Foo$Bar isn't even
nested; it's implemented as a top-level class named Foo$Bar. Surely you cannot
conclude from this that there are no such things as nested classes in Java.
But let's set aside what I said and talk about inner instances belonging to
outer instances. Define static, non-final X x inside Bar.
Assume Foo variables a and b reference different objects. a.x would belong to
a, and b.x would belong to b, by the rules of inner classes. But we said x is
static in Bar, so x does not belong to a or b. The inner-classness wants the
xes to be different but the staticness wants them to be the same. I can
imagine Gosling or whomever thinking that this is tricky and weird, and
somehow contrary to the notion of inner class things belong to an outer class
instance.
Besides, there is that little clause in the JLS that it would violate.
This isn't a defense of the syntax exactly. I am speculating on how it makes
sense to deny such static members given that they are denied, not trying to
say it's better than the alternatives.
So while it isn't maybe precisely true, although I think it is, that inner
classes belong to enclosing instances in Java, it sure is set up in the
language that you can think of it that way with impunity.
<http://www.javaworld.com/javaworld/javatips/jw-javatip75.html>
"nested classes are associated with the enclosing class itself, whereas inner
classes are associated with an object of the enclosing class."
<http://www.onjava.com/pub/a/onjava/excerpt/HardcoreJava_chap06/index2.html>
(Simmons, /Hardcore Java/, O'Reilly)
"To be an inner class, a class has to have instance scope."
and
"Formally, it can be said that an inner class is instance-scoped and a static
nested class is class-scoped. "
<http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html>
(The Sun Java Tutorial)
"an inner class is associated with an instance of its enclosing class"
- Lew
Now you're rewriting the JLS?
My other post shows how even Sun themselves speak of an inner class
associating with an instance.
- Lew
Where it needs it, yes.
Again, sloppy wording.
>
> <http://www.onjava.com/pub/a/onjava/excerpt/HardcoreJava_chap06/index2.html>
> (Simmons, /Hardcore Java/, O'Reilly)
> "To be an inner class, a class has to have instance scope."
> and
> "Formally, it can be said that an inner class is instance-scoped and a
> static nested class is class-scoped. "
Scoping is an entirely different issue. It would be equally true to say
that static methods are class-scoped and instance methods are
instance-scoped.
>
> <http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html>
> (The Sun Java Tutorial)
> "an inner class is associated with an instance of its enclosing class"
More sloppy wording.
One more question: In the following fragment:
class Foo
{
class Bar{ ...}
static Bar b;
}
What type is b?
Lew wrote:
>> Now you're rewriting the JLS?
> Where it needs it, yes.
My, my.
You see, I use the JLS as the authority on the Java language. I just don't
know how I could understand the language if I could just throw away parts of
the specification for it. I mean, how can one tell where it needs it, given
that the JLS defines the language?
Especially in light of the many other sources including the Sun tutorial, that
use the verbiage that an inner class is associated with an outer instance.
But if you feel you can define the language better than Sun and the JLS, I
sure don't know how we can have a meaningful discussion. I sort of have to
rest on those sources as the authority, and disputation of the JLS as prima
facie not tenable.
I thought I was doing a little forensics on the motivation for the banning of
non-final statics in inner classes, now I see we can't even agree on the
definition of the Java language. Based on authoritative sources, without
deconstruction or capricious rejection of parts of the JLS that I feel
"shouldn't" say what they actually do say, I will stick with thinking of inner
classes as being associated with outer class instances. Your way of describing
it really doesn't contradict that point of view anyway.
I really, really want to recommend that you not consider parts of the JLS as
wrong that way. It was very carefully written by a lot of people, and likely
says exactly what it intends to. Besides, by definition Java is what the JLS
says it is, so you fall into a weird solipsistic trap trying to second guess
the very defintion of the language, especially in this case where there is so
much supporting ancillary documentation.
- Lew
public static void main( String [] args )
{
Foo x = new Foo();
b = x.new Bar();
}
> }
>
> What type is b?
I see what you mean, but it still makes sense to say it the way the JLS and
Sun did, just not quite the way I thought. Let me explain.
I misspoke in my first statements when I said that the class was different for
each object - even as I said that I knew that class is always Foo.Bar. It is
the same class. So I see why one might think it is all right to relax the
inner class static variable rule that they must be final.
However, the JSL and Sun do not say that different instances have different
types, but that the class is associated with an instance. That is a runtime
phenomenon, "associated with", it looks like. So in the above snippet, b has
the class Bar that is associated with x. But unlike what I first said, the
type does not change. The association with a particular object changes.
Now I understand why you call their wording "sloppy". I think I get what they
mean, but it is not very understandable.
Now let me try to second-guess why they thought allowing non-final statics is
bad. It seems, perhaps, to break the association of these statics with outer
class objects, and the idea that static inner class variables could maybe need
access to outer class instance variables is just a mess. So they ducked the
whole issue by forbidding that kind of variable.
This kind of thinking would hold just as much under your way of describing
instances as being associated with outer instances - the question is whether
this would also apply to inner variables, and the question of access to outer
non-static variables remains, too. I think the designers just decided that it
wss better to stay out of the area then get caught up in the conflict with the
essential instanceness of inner classes with respect to outer ones.
I also can agree that Java could define non-final statics in inner classes if
the designers wanted it to. I have to wonder what other trouble that would
have caused that made them shy away from it. I find the consistent Sun
attitude, even if sloppy, that inner classes belong to outer instances to be a
strong forensic clue to the mindset that bans such statics.
- Lew
OK, ignore the places where I said that.
- Lew
Then I suggest you not read JLS 3. It's full of obvious mistakes and typos
in the new material, especially where it discussing generics.
>
> Especially in light of the many other sources including the Sun tutorial,
> that use the verbiage that an inner class is associated with an outer
> instance.
>
> But if you feel you can define the language better than Sun and the JLS, I
> sure don't know how we can have a meaningful discussion. I sort of have to
> rest on those sources as the authority, and disputation of the JLS as
> prima facie not tenable.
>
> I thought I was doing a little forensics on the motivation for the banning
> of non-final statics in inner classes, now I see we can't even agree on
> the definition of the Java language. Based on authoritative sources,
> without deconstruction or capricious rejection of parts of the JLS that I
> feel "shouldn't" say what they actually do say, I will stick with thinking
> of inner classes as being associated with outer class instances. Your way
> of describing it really doesn't contradict that point of view anyway.
>
> I really, really want to recommend that you not consider parts of the JLS
> as wrong that way. It was very carefully written by a lot of people, and
> likely says exactly what it intends to. Besides, by definition Java is
> what the JLS says it is, so you fall into a weird solipsistic trap trying
> to second guess the very defintion of the language, especially in this
> case where there is so much supporting ancillary documentation.
Where one sentence in a section contradicts the rest of it, I feel free to
assume that sentence is in error. I don't see how I could reasonably do
otherwise.
Are you saying now that there are many classes Foo.Bar, but all are the same
type? In Java (pre-generics, anyway), "class" and "type" are the same
thing.
Anyway, my question wasn't "What type is the object pointed to by 'b'?",
it's "What type is the reference 'b'?" I think we agree that it's Foo.Bar.
All of which (with the possible exception of the null type) are represented
by classes, e.g. Boolean.TYPE. And the following two sentences are
synonymous:
1. a and b are of the same class.
2. a and b are of the same type.
No, I was not saying that. I was agreeing with you that Sun's wording is
sloppy, and trying to make sense of what they really meant. I am now with you
in attempting to "rewrite" the JLS to make sense of what Java actually does
I was also trying to guess at the mindset that forbade
non-compile-time-constant statics in inner classes, and that led me into a
fuzzy world of memes and conceptual structures.
My initial confusion was caused by trustingtoo literally the verbiage Sun and
others provide . I understand now what you were saying and why I was wrong.
- Lew
OK. I'm clearly not understanding what you are saying, though.
By the way, I think the length and complexity of the conversation we've had
so far is evidence that inner class are pretty complicated :-)
> It occurs to me that many things left out of Java might seem very useful
> to highly skilled programmers for certain corner applications, but that
> the compromises may make life simpler for the gazillions of journeyman
> programmers who do not have quite that deep a grasp on computer science.
But introducing incomplete, and therefore inconsistent, hacks into the language
doesn't make things easier for /anybody/ -- working programmer or theorist.
Simplicity and generality are the things to aim for. Special cases, things
that should work but don't, things that require a theorists' understanding to
use, these are all things to avoid.
Leaving stuff out of the language is fine (albeit frustrating for those who
know how /much/ easier they make programming), since everyone knows where they
are, and simplicity (even the simplicity of emasculation) is a virtue in
itself. What I object to is introducing half-baked approximations to powerful
ideas into the language.
What Java is working towards is a list of more-or-less arbitrary special cases,
complicated by other stuff which (while also ridden with special-case
exceptions) is only comprehensible by theorists.
If a programmer doesn't even try to understand what s/he is doing, and only
programs by rote and by copying other examples, then the maze of exceptions
won't bother them. But I wouldn't want to hire or to work with, and absolutely
/never/ use software created by, any such "programmer".
-- chris
> This is the use of anonymous classes which would be solved equally well by
> method pointers, which are conceptually much simpler (or at least more
> familiar from other C-base languages.) I find Sun's white paper extolling
> the virtues of anonymous classes over method pointers quite unconvincing.
Now there, I agree with Sun (as far as I remember the paper). The guy (I
forget his name -- something Nordic) who introduced them into Delphi (or Object
Pascal or whatever it was then called), went on to introduce them into the
Borland C++ product (where they had no place /at all/), and then went to work
at MS where he has introduced them into everything (it seems) he touches.
The guy's a veritable Typhoid Lizzie. He suffers from some weird obsession
with the concept...
I don't think they have anything to do with, nor are in any way desirable as a
supplement for, OO programming. As an example to support this, in the
Smalltalk I use it is trivial to use the equivalent of "method pointers"
(actually they, MessageSends, are marginally more flexible and powerful).
What's more they are plug-compatible with the less powerful Messages (which
have no bound-in receiver), and with the vastly more powerful (but more
expensive) BlockClosures (which are full, stateful, closures) -- so there is no
barrier to using them whenever they fit the bill. But, in some 8 years as a
Smalltalk user, I have used them twice. Over that same period I must have used
thousands of BlockClosures and Message in contexts where I /might/ have chosen
a MessageSend.
-- chris
> I really, really want to recommend that you not consider parts of the JLS
> as wrong that way. It was very carefully written by a lot of people, and
> likely says exactly what it intends to. Besides, by definition Java is
> what the JLS says it is, so you fall into a weird solipsistic trap trying
> to second guess the very defintion of the language, especially in this
> case where there is so much supporting ancillary documentation.
The JLS is a complicated document, which has been carefully written, and
re-written, by some very precise and intelligent people. As such it is like a
large computer program -- it contains bugs. One of the perennial topics here
on C.L.J.P is discussion of whether some passage should be taken exactly as
written, needs to be "interpreted" a little, or is just plain wrong.
The JLS is an authority, true. It is /the/ authority. But, like anything of
human creation, it is not perfect.
Most typically, if the compiler seems to be doing something daft, it will turn
out that it is just following the rules laid down in the JLS, and that those
rules make perfect sense (even if they give rise to counter-intuitive
consequences sometime). Rather rarely (at least until recently) it will turn
out that the compiler is /not/ following the rules of the JLS, and is therefore
buggy. But there is an unknown, and unknowable, number of cases where the
compiler is getting it right, but if anyone traced the details down then they'd
find that JLS required different behaviour -- i.e. that the JLS was buggy.
Put your faith in it by all means, but keep your wits about you when you do.
-- chris
Anders Helsbeg.
> who introduced them into
> Delphi (or Object Pascal or whatever it was then called), went on to
> introduce them into the Borland C++ product (where they had no place
> /at all/),
Hmm? C++ has had method pointers as far back as I can recall. Certainly
they were described in the ARM.
> and then went to work at MS where he has introduced them
> into everything (it seems) he touches.
I don't know if he was at MS early enough to have introduced them into J++.
He may well have been the one who introduced them into the .NET CLR.
One interesting thing about Sun's white paper is that it was written at a
time when Sun was suing MS for polluting Java with, among other things,
method pointers.
Eh? You've been having a conversation about the confusion of saying
that a class has an instance concept. You could have had exactly the
same conversation about incorrect terminology if I had said "the String
class maintains a char[] to store its data". Are instance variables
pretty complicated?
--
Chris Smith
> > > This is the use of anonymous classes which would be solved equally
> > > well by method pointers, which are conceptually much simpler (or at
> > > least more familiar from other C-base languages.) I find Sun's
> > > white paper extolling the virtues of anonymous classes over method
> > > pointers quite unconvincing.
> >
> > Now there, I agree with Sun (as far as I remember the paper). The
> > guy (I forget his name -- something Nordic)
>
> Anders Helsbeg.
Thanks.
> > who introduced them into
> > Delphi (or Object Pascal or whatever it was then called), went on to
> > introduce them into the Borland C++ product (where they had no place
> > /at all/),
>
> Hmm? C++ has had method pointers as far back as I can recall. Certainly
> they were described in the ARM.
Not in the same sense as I meant. C++ has had pointers to methods for as long
as I can remember too, but the "method pointers" Helsbeg always squeezes in are
/bound/ method pointers[*] -- fixing not just the method, but also the
receiver. Did you mean something other than those ? I assumed you were
meaning Helsbeg-style "method pointers", since I don't see how pure
pointers-to-methods solve many of the problems addressed by inner classes --
and Java has those anyway, instances of java.lang.reflect.Method.
([*] Actually, now I come to think of it, I'm not certain that he did call them
"method pointers", maybe it was "delegates" ?)
> > and then went to work at MS where he has introduced them
> > into everything (it seems) he touches.
>
> I don't know if he was at MS early enough to have introduced them into
> J++. He may well have been the one who introduced them into the .NET CLR.
I think he was (and I think I remember blaming him at the time). I'm not
certain, though, and I haven't tried to check.
> One interesting thing about Sun's white paper is that it was written at a
> time when Sun was suing MS for polluting Java with, among other things,
> method pointers.
Yes, I (too?) have always assumed that there was more than just technical
motivations behind that paper.
-- chris
I saw it as being about how inner classes/instances are related to their
enclosing classes/instances. No concept of "enclosing", no discussion.
That's what I meant. Since this discussion was about complexity of
concepts, I conflated the two, since they're both (more or less) the concept
"object that encapsulates a method call".
> I assumed you were meaning Helsbeg-style "method pointers",
> since I don't see how pure pointers-to-methods solve many of the
> problems addressed by inner classes -- and Java has those anyway,
> instances of java.lang.reflect.Method.
Ick. One of the nice things about bound method pointers is that they're
type correct, and far easier to use than instances of Method. There's no
chance of causing any of the "I screwed up the parameters" exceptions, and
no need to package up exceptions thrown by the caller into an
InvocationTargetException.
>
> ([*] Actually, now I come to think of it, I'm not certain that he did
> call them "method pointers", maybe it was "delegates" ?)
That's what they're called in C#. I don't know what they were called in
J++.
>
>
>> One interesting thing about Sun's white paper is that it was written
>> at a time when Sun was suing MS for polluting Java with, among other
>> things, method pointers.
>
> Yes, I (too?) have always assumed that there was more than just
> technical motivations behind that paper.
Too, yes :-)
Is there any source of confusion you can point out that doesn't
translate to instance variables rather than inner classes? The only
thing I saw was that when the JLS says "each inner class has ...", it
should have said "each object of an inner class has ...". Other than
that, it's pretty straight-forward.
(Note that I'm not saying there is no complexity involved in the concept
of inner classes. Certainly some of the sequencing of steps involved in
creating them is tricky to understand. I just think it's naive to
believe that tricky issues don't exist with other approaches to those
problems. I also don't see that delegates provide the same advantages,
as they still require the declaration of a named entity "somewhere
else" to accomplish the interactions desired.)
--
Chris Smith
> Is there any source of confusion you can point out that doesn't
> translate to instance variables rather than inner classes? The only
> thing I saw was that when the JLS says "each inner class has ...", it
> should have said "each object of an inner class has ...". Other than
> that, it's pretty straight-forward.
I don't think so (and I don't think there was all that much actual confusion
involved).
The question (as I see it as an outsider to the conversation) that this
subthread raised is one that I hadn't considered before -- and which I find
quite interesting. Given two objects created in separate runs of a method with
an inner class, what is the class relationship between them ?
Up until this conversation, I would have replied unhesitatingly that they were
of the same class (which is true, of course). But is that the /intended/
picture of the Java design ? Lew has raised the possibility (which I find
plausible) that the intended picture was that that their concrete classes are
unrelated (beyond having a common supertype). Without that assumption, I can't
make any sense at all of the designers' decision not to allow static members in
inner classes -- there is not the slightest semantic or technical advantage in
forbidding them.
This reminds me a bit of the peculiar way that "static" is treated in many
places in Java (Java spec, JVM spec, Java recommended coding conventions). I
have come to believe that the intended picture for static members was that they
were somehow shared between /all/ the instances of a class, rather than that
they were not attached to /any/ instance.
Now to me that picture of "static" is just plain daft. And the banning of
static members of inner classes is daft too. But if that's the way(s) the
designers' minds were running, then at least the daftness is comprehensible.
-- chris
> Up until this conversation, I would have replied unhesitatingly that
> they were of the same class (which is true, of course). But is that
> the /intended/ picture of the Java design ? Lew has raised the
> possibility (which I find plausible) that the intended picture was
> that that their concrete classes are unrelated (beyond having a
> common supertype).
Right. That interpretation would require that each time a Foo.Bar is
created, its type is a subclass of Foo.Bar associated with the enclosing
Foo I reject this by Occam's Razor: it literally multiplies entities
unnecessarily. [1] But I can't disprove it entriely [2], and Lew did a good
job arguing for it.
.
1. And leads to the question: Why is Java creating types dynamically here,
but not with generics where it would actually be useful?
2. Though the fact that foo.bar.getClass() equals the one and only
Foo.Bar.class is strong evidence.
It was also limited and unable to solve some important problems. However, I
think this is a common problem with any technology. Particularly if the
original visionaries have left, and been replaced with less creative and
more propeller-headed engineers.
Inner classes are a great way of implementing event handlers and callbacks
without cluttering up the outer class's API.
> --
> C. Benson Manica | I *should* know what I'm talking about - if I
> cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
I would have done so, as well. I don't see the other view point. I
read Lew's comments, and I realize that's what he was saying. However,
I just assumed he was trying to see how far he could stretch the JLS
language for fun. It never occurred to me that anyone thinks there is a
reasonable interpretation other than that classes are associated one-to-
one with syntax, such that one bit of syntax (i.e., a piece of code that
declares an inner class) creates one class (within the context of a
given ClassLoader).
> This reminds me a bit of the peculiar way that "static" is treated in many
> places in Java (Java spec, JVM spec, Java recommended coding conventions).
I am, just like you, sometimes baffled by the choices of the language
with regard to static variables. I am not at all sure that any one
conception of static variables explains all of the oddities in Java's
treatment of statics. Really, you have to trace every one down to
someone's not foreseeing a use somewhere, and following the earlier
precedent to arbitrarily deny the use of static variables when it seems
right.
--
Chris Smith
Nope. I really was actually trying to follow what I thought Sun was saying,
and I really wastrying to understand inner classes as being bound by their
enclosing instances somehow. I mean, that is what they told me, and perhaps
naively, I tried to twist it into my world view.
That's what I get for treating the JLS as the literal Java Bible, I suppose.
- Lew
> The
> revolutionary idea is that your choice of building abstractions no
> longer has to follow the structural needs of code in terms of
> implementing interfaces and such. The general idea of decoupling those
> was pretty unprecedented among mainstream OO languages.
I suppose it depends on how you see them. To me inner classes are pretty-much
syntactic sugar for "ordinary" classes. Important syntactic sugar, to be sure,
since they "feel" much less heavyweight than a full top-level class. And that
lightweight feel is important if programmers are to be comfortable using the
kinds of decoupled/inverted code structures they are intended to support.
Their virtue, it seems to me, is almost entirely a matter of perception (a sort
of placebo effect). I agree that they work -- it is now routine to see code
structures which (if expressed as normal classes) would have been considered
"advanced", or even obscure. But it is just a (benign) con-job. Parents try
similar tricks to persuade children to eat their greens ;-)
> As useful as it
> would have been to be able to access local variables as well, that would
> have merely added an implementation technique; it doesn't extend into
> the design sphere.
Agreed. For them to extend the design space, they would have to provide
something more like Smalltalk's BlockClosures -- the ability to control
execution in the outer method, not just to share variable bindings with it.
And would probably need to be even lighter-weight syntactically (just for the
same "con-job" reasons).
> > + The anonymous class syntax is a disgrace.
>
> Is there something you'd prefer?
I'd be quite happy to see it vanish altogether. Defining a method, inside a
class, inside a new() expression, (and usually inside a method call parameter
list, to boot!), is /far/ too much syntax -- unreadable and impossible to lay
out sensibly.
> The current syntax opens the door to removing that
> restriction in the future without having some clumsy field-copying
> syntax left lying about.
I have this bridge you might be interested in buying...
> > And is there really that much benefit in inner classes over the classic
> > closure concept ? I'm not sure, though I'd be willing to argue the
> > case either way. Someday I must scan rt.jar to see how many inner
> > classes implement more than one method.
>
> Given that Java lacks first-class functions, I'd say it would have
> complicated the language more to add them instead of anonymous classes.
I don't really see that there's all that much difference (assuming that you
don't want full Smalltalk-style closures). Simply take the current inner class
implementation, and restrict the inner class to exactly one method, and bob's
yet uncle. Most of the current syntax for anonymous inner classes then becomes
redundant, and so can be considered implicit and removed. And (ta da!) you
have a nicer and an even lighter-weight syntax with little reduction in
expressive power.
No first class functions necessary ;-)
BTW, I did run a scan of rt.jar from 1.6.0. Out of 15854 classes, 1717 are
inner (of which 1546 are anonymous), and of those 296 (242 anonymous) have more
than one explicit method -- which is a higher proportion than I had expected.
-- chris
> > This reminds me a bit of the peculiar way that "static" is treated in
> > many places in Java (Java spec, JVM spec, Java recommended coding
> > conventions).
>
> I am, just like you, sometimes baffled by the choices of the language
> with regard to static variables.
More than just the wording. The lookup algorithm for resolving method calls at
runtime starts by looking for a matching method, and only when one is found
considers whether its static-ness matches the invoking bytecode!
-- chris
This, I think, is a consequence of the abomination (inherited from C) of
being able to access a static member via a reference as well as via the
class name, and not wanting to have two different sets of lookup rules for
the two cases.
frustrated...@gmail.com wrote on 22 Feb 2007 02:28:05 -0800 in
comp.lang.java.programmer:
>When Java first become popular I remember it being touted as having
While I don't agree with you top posting - I agree with what you said.
Inner classes and generics are useful tools - and for someone who knows how
to program they add a negligible degree of depth to the language.
It's my opinion that there is nothing wrong with being confused about
something, or not understanding something. But to say that there is a
fundamental problem with the system (in this case Java) when you don't even
know what you're talking about is a little offensive.
--
LTP
:)
"Inherited from C?" Since C has no classes, no class
members to be referred to, and no class names to use or not
use as references to those non-existent members of the non-
existent classes, tracing the inheritance seems iffy.
> This, I think, is a consequence of the abomination (inherited from C) of
> being able to access a static member via a reference as well as via the
> class name, and not wanting to have two different sets of lookup rules
> for
> the two cases.
I think it has more to do with the "static" modifier not being part of the
method's signature (ie. its unique name) but representing a property of
it. Which can only be checked after finding it by the signature "label".
To differentiate static and non-static methods (with the same signature
otherwise) you would need to add some static/instance component to the
name. And the internal names of methods look mangled enough as it is. :)
C++, that is.
Ironic that this is brought up in a (trolling?) thread titled "Has
Java become too complicated?".
- Oliver