Skip to main content
gamedev.net
🔒 Locked

[java] Weird code trick (inner class, presumably)

Started by Thygrrr Nov 27, 2004 at 8:09 AM 19 replies 3.3k views
Original Post
Thygrrr
Thygrrr
I found this piece of code in a J2ME project I inherited. The whole thing was written by a person who apparently never heard of arrays and switch/case statements and was generally a horribly inefficient and sloppy coder. Also, the file had some incorrectly nested inner classes, horrid indentation, etc. Hence, I am not sure what to think of the following piece of code. Honestly - it compiles! So, could any of you Java veterans tell me what he's doing from a syntactic perspective, and what will happen during compilation of said code snippet? And, does it actually work the way it's intended to (apparently call method setStart() three seconds later)? [Edited by - Thygrrr on November 27, 2004 8:38:09 AM]
andrewk3652
andrewk3652
Quote:
Original post by Thygrrr

Honestly - it compiles!


It's ugly, but yes it works as designed. One thing I had trouble when transferring over from C++ was the concept of java being able to override and create classes on the fly. So what he's actually doing there is creating a new TimerTask, and overriding its run() method on the fly. So what he's getting there is a one-use class that is important enough to be needed, but not important enough to be given its own class file. This is common for a class that you're only going to need ONE TIME, for ONE THING. Java lets you do this, as strange as it is to the C++ brain. :-) Maybe my comments will explain better.

public void startTimer() {    TimerTask task = new TimerTask() {        // thanks to Java, we can override the run()        // method (or whatever else we wanted to)        // for this specific implementation of TimerTask        // on the fly.        public void run() {            // in this particular case, we modify it because            // we want this particular breed of TimerTask to            // call setStart() whenever it runs (whatever this            // does) instead of its usual behaviour            setStart();        }    }; // there - done. The rest of the TimerTasks in the    // source code, globally, will behave as normal. Only this    // one will be effected.    timer = new Timer();    timer.schedule(task, 3000); // schedule it to do whatever it    // does, and do it every 3000 milliseconds}


Hope that helped

(edit: I personally think that this is *horrendous* coding style and should be avoided at just about all costs... it makes code damn near impossible to read, even when you know what you're looking at. But to each their own.)
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
Thygrrr
Thygrrr
Wow, thanks for the really detailed reply. I think overriding classes on the fly might be a little similar to lambda functions in Python (and originall, FORTRAN, wasn't it?). Little throwaway objects.

I think these might come in handy for quick tests, but generally, I'D stay away from then. That code is damn near impossible to read, and the first thign you expect is that someone accidentally copy/pasted something into a block in the wrong place.

Will this coding 'technique' result in an additional .class file being generated?

(and, for laughs: a snippet from the same source file)

Of course I decided to rewrite this mess from scratch... :p~
andrewk3652
andrewk3652
My god, whose source code are you taking over? Bill gates?

No, there won't be an additional .class file generated - this is all handled at runtime. There will be an object of appropriate size created on the heap, tho.

No prob about the reply. I tend to be very long-winded, and unable to compress my descriptions.

cat andrew | tar --create --gzip > just_shutup.tgz
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
CaptainJester
CaptainJester
What he is doing there is call an anonymous class. It is created on the fly for use in that one location. It does have its uses, but I tend to avoid it because it does make code harder to read.

Quote:
Original post by andrewk3652
No, there won't be an additional .class file generated - this is all handled at runtime. There will be an object of appropriate size created on the heap, tho.


Wrong. There will be a class file generated for each anonymous class used. If that example were in a file call Test.java, then Test.class and Test$1.class will be generated.
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][
andrewk3652
andrewk3652
Quote:
Wrong. There will be a class file generated for each anonymous class used. If that example were in a file call Test.java, then Test.class and Test$1.class will be generated.


I stand corrected
=========================Buildium. Codium. Fragium.http://www.aklabs.net/=========================
Thygrrr
Thygrrr
Quote:
Original post by CaptainJester
Wrong. There will be a class file generated for each anonymous class used. If that example were in a file call Test.java, then Test.class and Test$1.class will be generated.


Thanks for clearing that up :)

Yes, anonymous class as in anonymous function. I hope to remember this term for future reference! Thanks to all of you.

And no, the code wasn't written by Bill Gates, haha! (I actually estimate Billy to be at least a somewhat decent coder, at least with regard to BASIC in the late 70s!)
hplus0603
hplus0603
FORTRAN did not have lamdas; FORTRAN is as static as a language can get. I believe lambdas (a k a closures) were introduced with the whole functional programming revolution; LISP and PL/1 and Haskell and all that.
enum Bool { True, False, FileNotFound };
Thygrrr
Thygrrr
INNER CLASSES:
I personally dislike them. Apparently a large bunch of J2ME coders uses them, but I believe that inner classes prevent code reuse, make the code difficult to read, harder to write, and are often misused. This will result in no gain whatsoever. The actual motivation for the J2ME people I talked to was to use inner classes to cut down on the number of .class files in the .jar - I still don't know whether that's entirely possible.


FORTRAN vs LISP:
Yeah, LISP. My bad. I thought "Was it LISP? Don't really know what it is, and lambda sounds scientific. Probably has to do with FORTRAN, then, because I at least basically know what FORTRAN stands for". Thanks for straightening it out. I only know lambdas from Python.

But I did bother to check ("wasn't it?") :)
Raghar
Raghar
I would do it this way:
   addTimmerTask(new Runnable(){public void run(){setStart();}}, 3000);or better like this:   addTimmerTask("start", 3000);Inner classes and annonymous classes are very nice when you don't like to bother yourself with a something more complex, or stupid.buttonYUCK.addActionListener({new ActionListener(){             public void ActionPerformed(ActionEvent e){do some stuff}});

Its rather nifty this way.

Inner classes are supposed to control code around them. They don't prevent a code reuse, you still have one class that you can extend, or copy and paste.

Could someone modify this board so source code window would be smaller? It's annoying when you are posting three small pieces of a code.
Luctus
Luctus
Quote:
Original post by Thygrrr
I think these might come in handy for quick tests, but generally, I'D stay away from then. That code is damn near impossible to read, and the first thign you expect is that someone accidentally copy/pasted something into a block in the wrong place.

Actually, they're quite nice when implementing interfaces/adapter classes, like so:
class Foo	extends JPanel{	private MouseAdapter mouse = new MouseAdapter()	{		public void mousePressed( MouseEvent e )		{			// stuff		}		public void mouseReleased( MouseEvent e )		{			// stuff		}	};	public Foo()	{		addMouseListener( mouse );	}}

It takes a while to get used to it though.

Quote:

(and, for laughs: a snippet from the same source file)

Yuck [sick]
-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams
CaptainJester
CaptainJester
Quote:
Original post by Thygrrr
(and, for laughs: a snippet from the same source file)


OH MY GOD!!!

Multi-dimensional arrays exist in J2ME. Have they not heard of them?
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][
MadLep
MadLep
I use anon inner classes fairly regularly. If you know the syntax it's often cleaner to do it that way than to create a full named inner class.

They're useful for very specialised implementations of interfaces that are only used in one place (listeners in Swing are a perfect example).

If the guy that wrote the original code had indented and formatted it a bit better the intent would be clearer (a comment or two wouldn't have hurt either).
"I pretend to work, they pretend to pay me."
Thygrrr
Thygrrr
Yes, I think creating a tiny anonymous class that has only one overridden and very simple function is okay and can be quite useful. Those anonymous classes can seemingly be declared/defined anywhere in Java - handy!

I might end up using it, as well (though every additional class in J2ME should be carefully evaluated whether it's really needed.

[Edited by - Thygrrr on November 28, 2004 4:19:58 AM]
Zahlman
Zahlman
Be warned, inner classes "cost" a lot more for J2ME development than normal ones :( You really really shouldn't do this kind of thing in J2ME if there's any sane alternative.

Anyway. What's the fun in using anonymous constructs if you're going to declare a temporary? >:)

public void startTimer() {  timer = new Timer();   // I assume this is a class member so that the timer can be  // stopped later. Otherwise you could just do  // "new Timer().schedule(<etc.>". :)  timer.schedule(new TimerTask() {     public void run() {      setStart();    }  }, 3000);}


As for "diligence.gif", whoever wrote that needs to be fired. Right away. Actually, give them a couple minutes first to explain why the last parameter of the drawStringArray() call needs to be different for the his=3, her=3 case, or the last parameter of wrapStringToArray() need to be different for his=2, her=1. And fire whoever coded "drawStringArray", too, for requiring a length parameter that can be obtained from the input array anyway. (Unless "textArray.length" and 0 are supposed to be endpoints for a range in the array, in which case (a) they should be the other way around and (b) the method is badly named.)
Thygrrr
Thygrrr
He was fired a couple of days ago.

What's most apalling is that, even in the design document, everything is in a Matrix. It has "ARRAY" written all over it, honestly. Also, switch/case seemed beyond him, and look at this creative use of drawSubString ...

The last parameter in his/her being 1/2 is 150 because that's from a different platform with a different display resolution. He must have changed the parameters by hand. Note that this source code, in various versions and packages, exists in a dozen projects for a dozen handsets. I18N would take forever and is not quite correct, there are German and English versions ATM and we're negotiating with a publisher from Finland to make a Finnish one. The ~64 strings are "private final string" constants in the class. ICKY!!! I wrote a small routine spanning 5 lines of code that loads them from a .properties file instead, teehee.

As for your additional code twist: Nifty, nifty! That's actually quite nice to look at. Ranks right up there with recursion and robust exception handling code :)
RipTorn
RipTorn

Urgh. This brings back very bad memories...

I'm not a fan of java, especially inner classes and some of it's other weirdness, but this year.... ohh god

A small group project over around 6 months.. One guy was utterly awful..

In his one 2000 line code file,
there was one class,
in which there was one method,
that method being a constructor,
inside that constructor,
I stopped counting at 70 inner classes.

This constructor created a 'wizard' that had up to 5 levels of windows associated. And of course, there wasn't a single comment, not even a blank line, let alone any real indentation.. And far worse things. but thats off topic..

[tears]
Thygrrr
Thygrrr
Quote:
I stopped counting at 70 inner classes.


SHRIEK!

The Art of Kung-Foo eludes the feeble of mind, Glasshopper.
This man's Code-Foo is not schtrong.

Ironically, the dilligence.gif and two-dimensions.gif examples were written by a Chinese person.

Since this is rather OT already - I personally like Java. Lots! All it really lacks is Operator Overloading and null references / zero integers that may be automagically cast to boolean false.

[Edited by - Thygrrr on November 28, 2004 5:47:23 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.