From: Simon Wistow Date: 22:37 on 04 Apr 2008 Subject: Java's anonymous inner classes So Jav allows you to have anonymous inner classes. For example this is a really easy (if ugly) way to run something asynchronously new Thread(new Runnable() { public void run() { // do some stuff } }).start(); All well and good. But there is one down side. Say you want to, let's say, increment a counter; int counter = 0; new Thread(new Runnable() { public void run() { counter++; } }).start(); Perfectly reasonable, right? BZZZZZZZZZZZZZZZZZZZT! Wrong! You can't access anything other than final variables from within an anonymous class. Which means that final int counter = 0; new Thread(new Runnable() { public void run() { counter++; } }).start(); doesn't work because, well, counter is final. So how do you get around this? final int[] counter = { 0 }; new Thread(new Runnable() { public void run() { counter[0]++; } }).start(); I mean. Seriously. What The Fuck? Of course this gets extra special fun if you want to do something with exceptions. Let's say you want to do try { final Foo foo = FooFactory.getFoo(); Bar.doSomething(new BarRunner() { public void quux() { foo.execute(); } }); } catch (SomeCommonException e) { System.err.println("Got an exception: "+e); } finally { FooFactory.release(foo); } Well you can't because the finally clause won't see the foo object but you can't do final Foo foo; try { foo = FooFactory.getFoo(); Bar.doSomething(new BarRunner() { public void quux() { foo.execute(); } }); } catch (SomeCommonException e) { System.err.println("Got an exception: "+e); } finally { FooFactory.release(foo); } because that doesn't make sense. So what you have to do is Foo foo; try { foo = FooFactory.getFoo(); runBar(foo); } catch (SomeCommonException e) { System.err.println("Got an exception: "+e); } finally { FooFactory.release(foo); } public void runBar(final Foo foo) { Bar.doSomething(new BarRunner() { public void quux() { foo.execute(); } }); } And people wonder why Java has a reputation as being verbose? *sigh*
From: Marco Von Ballmoos Date: 22:59 on 04 Apr 2008 Subject: Re: Java's anonymous inner classes On Apr 4, 2008, at 23:37, Simon Wistow wrote: > So Jav allows you to have anonymous inner classes. You had me at "Java language feature". > I mean. Seriously. What The Fuck? All aboard for the Java bitch train! Woo-woo! I you like Java's current approach to functional programming, can I interest you in their unique approach to generics? I especially like the wildcard operator. I had so much fun, I ranted about it elsewhere: <http://earthli.com/news/view_article.php?id=1436>. A long time ago. Back when I still used Java. C#'s generics are better, but still forbid covariance, which is a royal pain-in-the-ass more often than the language designers clearly thought it would be. -- Marco Von Ballmoos http://earthli.com - Home of the earthli WebCore; PHP web sites made simple.
From: Peter da Silva Date: 00:22 on 05 Apr 2008 Subject: Re: Java's anonymous inner classes On 2008-04-04, at 16:59, Marco Von Ballmoos wrote: > http://earthli.com/news/view_article.php?id=1436 Is this all part of the generic hate created by the decision to avoid late binding at all costs, or is there some other source of hate here?
From: Marco Von Ballmoos Date: 08:08 on 05 Apr 2008 Subject: Re: Java's anonymous inner classes On Apr 5, 2008, at 01:22, Peter da Silva wrote: > On 2008-04-04, at 16:59, Marco Von Ballmoos wrote: >> http://earthli.com/news/view_article.php?id=1436 > > Is this all part of the generic hate created by the decision to > avoid late binding at all costs, or is there some other source of > hate here? Erasure was a much better 80s band than programming language concept. It's exactly the kind of generics you can expect if you avoid changing the existing library (*don't touch* reflection) and VM (and, for God's sake, don't ever, ever, ever touch the JVM instruction set) at all costs. -- Marco Von Ballmoos http://earthli.com - Home of the earthli WebCore; PHP web sites made simple.
From: Aristotle Pagaltzis Date: 22:25 on 05 Apr 2008 Subject: Re: Java's anonymous inner classes * Marco Von Ballmoos <mvonballmo@xxxxx.xxx> [2008-04-05 00:10]: > C#'s generics are better, but still forbid covariance Have to, to ensure type safety. Regards,
From: Marco Von Ballmoos Date: 22:04 on 06 Apr 2008 Subject: Re: Java's anonymous inner classes On Apr 5, 2008, at 23:25, Aristotle Pagaltzis wrote: > * Marco Von Ballmoos <mvonballmo@xxxxx.xxx> [2008-04-05 00:10]: >> C#'s generics are better, but still forbid covariance > > Have to, to ensure type safety. "Have to" is a bit strong. "Willing to accept the restriction on expressiveness in exchange for an absolutely foolproof type system" is more accurate. The classic problem with covariance is that it becomes possible to generate -- quite unwittingly -- a configuration of objects that is statically valid, but dynamically invalid. I wrote an article a while back about an interesting paper on the subject: http://earthli.com/news/view_article.php?id=820 It turns out that this much-feared situation of dynamic invalidity doesn't come up so much in practice. It's a matter of opinion whether the absolute safety from such a slim possibility is worth the reduction of expressiveness. Granted, one can get around many matters of invariance by declaring a method as generically-typed, but this increases the complexity of the language and is not a solution for third-party frameworks. In the case of frameworks, it's a pity that, given A inheriting from B and the following framework method: void DoSomething(IList<Base> list); One has to call it like this: IList<B> bList; // do B-specific stuff DoSomething((IList<A>)bList); Which incorporates a cast and dodges type-safety anyway. One can argue that framework methods accepting generic types should always have a generic parameter, like this: void DoSomething<T>(IList<T> list); Which isn't so bad, but it needlessly propagates pointy brackets throughout the code and doesn't really make things any clearer. I would argue that more people would intuitively think that IList<B> inherits from IList<A> if B inherits from A than that it does not (and that generic methods are instead required). Cheers Marco P.S. I'm not really trying to pimp my article here; I'm just too lazy to incorporate everything into this mail. -- Marco Von Ballmoos http://earthli.com - Home of the earthli WebCore; PHP web sites made simple.
From: Peter da Silva Date: 00:02 on 07 Apr 2008 Subject: Re: Java's anonymous inner classes That is a very interesting paper on type-safe covariance. I will have to think about it, but it may be enough to make me abandon my position that statically bound languages inevitably lead to developers recreating the problems of dynamically bound ones anyway.
From: Yossi Kreinin Date: 08:28 on 07 Apr 2008 Subject: Re: Java's anonymous inner classes Marco Von Ballmoos wrote: > On Apr 5, 2008, at 23:25, Aristotle Pagaltzis wrote: >> * Marco Von Ballmoos <mvonballmo@xxxxx.xxx> [2008-04-05 00:10]: >>> C#'s generics are better, but still forbid covariance >> >> Have to, to ensure type safety. > It's a matter of opinion whether > the absolute safety from such a slim possibility is worth the reduction > of expressiveness. My Java is quite rusty, but aren't Java methods supposed to declare their exceptions, and wouldn't a theoretical possibility of a ClassCastException thus be a problem with generic methods? > I would > argue that more people would intuitively think that IList<B> inherits > from IList<A> if B inherits from A than that it does not (and that > generic methods are instead required). > I think that the only reasonable test for "is Y a subclass of X?" is "can I substitute Y objects whenever X objects are used?". Y="collections of derived class objects" fails this test when X="collections of base class objects". Now, lots of actual OO users never use the substitutability test, hence the Rectangle classes derived from Triangle and vice versa. Should a language designer care about the intuition of these people?
From: Philip Newton Date: 10:07 on 07 Apr 2008 Subject: Re: Java's anonymous inner classes On Mon, Apr 7, 2008 at 9:28 AM, Yossi Kreinin <yossi.kreinin@xxxxxxxx.xxx> wrote: > My Java is quite rusty, but aren't Java methods supposed to declare their > exceptions, Only checked exceptions, i.e., everything not derived from RuntimeException or Error. (Otherwise you'd have to declare things such as "may throw NullPointerException" or "may throw JvmOutofMemoryError [or whatever it's called]" all over the place.) > and wouldn't a theoretical possibility of a ClassCastException > thus be a problem with generic methods? ClassCast Exception is a subclass of RuntimeException, and therefore an unchecked exception that can arise at any time without needing to be declared. Cheers,
From: Marco Von Ballmoos Date: 20:36 on 08 Apr 2008 Subject: Re: Java's anonymous inner classes On Apr 7, 2008, at 09:28, Yossi Kreinin wrote: >> I would argue that more people would intuitively think that >> IList<B> inherits from IList<A> if B inherits from A than that it >> does not (and that generic methods are instead required). > > I think that the only reasonable test for "is Y a subclass of X?" > is "can I substitute Y objects whenever X objects are used?". > Y="collections of derived class objects" fails this test when > X="collections of base class objects". I agree with the test of "can I substitute Y objects whenever X objects are used?", but I don't follow -- in your example -- under which circumstances I would be unable to substitute IList<B> wherever IList<A> is expected. (All examples are in untested C#.) If covariance is supported, then I can do the following: class A { property bool IsAvailable { get; set; } property string Name { get; } void Save(Stream stream); } class B : A { property int NumAttempts { set; } void UpdateFromWeb(); } void PlayWithAList(IList<A> list) { Stream stream = new MemoryStream(); foreach (A a in list) { if (a.Name == "test1") { a.IsAvailable = !a.IsAvailable; } a.Save(); } } void main() { IList<B> bList = GetListFromWebService(); PlayWithAList(bList); } Where can I not substitute A with B in the method "PlayWithAList"? Without covariance, I can write the method like this: void PlayWithAList<T>(IList<T> list) where T : A { // body is the same } As mentioned in the previous mail, this works just fine *as long as I have control of the method definition*. If the method definition is in a framework and the designer didn't make the method generic, then you're out of luck and have to either convert or cast the argument, which is a shame. Granted, with containers, you leave yourself open to the possibility of adding an element to the list which will cause a runtime error. Suppose we also have class C: class C : A { } void PlayWithAList(IList<A> list) { list.Add(new C()); } If I'd passed in IList<B> as the parameter to this method, it would cause a runtime exception even though the compiler had evaluated statically that it was legal. Interestingly, C# does support covariance in one limited case: when calling delegates. Assume the following delegate definition: delegate void PlayWithA(A a); Then let's redefine the method call "PlayWithAList" to be: void PlayWithAList(IList<A> list, PlayWithA func) { Stream stream = new MemoryStream(); foreach (A a in list) { if (a.Name == "test1") { a.IsAvailable = !a.IsAvailable; } func(a); a.Save(); } } Since C# supports covariance, you can call "PlayWithAList" like this: void main() { IList<B> bList = GetListFromWebService(); PlayWithAList( bList, delegate(B b) { b.UpdateFromWeb(); // Method is only defined in B, but covariance works here! } ); } Cheers Marco -- Marco Von Ballmoos http://earthli.com - Home of the earthli WebCore; PHP web sites made simple.
From: Michael Poole Date: 02:06 on 09 Apr 2008 Subject: Re: Java's anonymous inner classes Marco Von Ballmoos writes: > On Apr 7, 2008, at 09:28, Yossi Kreinin wrote: > >>> I would argue that more people would intuitively think that >>> IList<B> inherits from IList<A> if B inherits from A than that it >>> does not (and that generic methods are instead required). >> >> I think that the only reasonable test for "is Y a subclass of X?" >> is "can I substitute Y objects whenever X objects are used?". >> Y="collections of derived class objects" fails this test when >> X="collections of base class objects". > > > I agree with the test of "can I substitute Y objects whenever X > objects are used?", but I don't follow -- in your example -- under > which circumstances I would be unable to substitute IList<B> wherever > IList<A> is expected. Suppose you receive an IList<A> and try to append an instance of A to it. This operation is only valid on an instance of IList<B> if the new object is also an instance of B. There are probably other instances of why covariance cannot cross container boundaries, but that is an easy one to remember. Michael Poole
From: Marco Von Ballmoos Date: 20:01 on 09 Apr 2008 Subject: Re: Java's anonymous inner classes On Apr 9, 2008, at 03:06, Michael Poole wrote: >> I agree with the test of "can I substitute Y objects whenever X >> objects are used?", but I don't follow -- in your example -- under >> which circumstances I would be unable to substitute IList<B> wherever >> IList<A> is expected. > > Suppose you receive an IList<A> and try to append an instance of A to > it. This operation is only valid on an instance of IList<B> if the > new object is also an instance of B. There are probably other > instances of why covariance cannot cross container boundaries, but > that is an easy one to remember. Yeah. I get that. It was one of the examples in the previous mail. I would, however, be willing to accept the risk in exchange for the increase in expressiveness. I'm taking issue with the line that "if it's not 100% statically provable, then it doesn't go in", regardless of how useful it would be. Plus, as mentioned in a link up-post, there are ways of getting around the provability problems as well. That's all I'm saying. -- Marco Von Ballmoos http://earthli.com - Home of the earthli WebCore; PHP web sites made simple.
From: Aristotle Pagaltzis Date: 20:34 on 09 Apr 2008 Subject: Re: Java's anonymous inner classes * Marco Von Ballmoos <mvonballmo@xxxxx.xxx> [2008-04-09 21:05]: > I would, however, be willing to accept the risk in exchange for > the increase in expressiveness. Well, the problem is, if you're willing to risk that, you can just do the job without generics -- just use a regular container and cast when you take an object out of it, the way you used to do before generics were added. The entire point of generics is to allow for moving that type check from runtime to compile time. [PS.: can people please take me out of CC when replying on this subthread. I am already subscribed to the list proper and don't need an extra copy of each mail. Thanks.] Regards,
From: Peter da Silva Date: 21:05 on 09 Apr 2008 Subject: Re: Java's anonymous inner classes On 2008-04-09, at 14:34, Aristotle Pagaltzis wrote: > Well, the problem is, if you're willing to risk that, you can > just do the job without generics -- just use a regular container > and cast when you take an object out of it, the way you used to > do before generics were added. But that means that instead of having a remote risk of a run-time exception, you're completely abandoning type-safety.
From: Marco Von Ballmoos Date: 21:54 on 09 Apr 2008 Subject: Re: Java's anonymous inner classes On Apr 9, 2008, at 22:05, Peter da Silva wrote: > On 2008-04-09, at 14:34, Aristotle Pagaltzis wrote: >> Well, the problem is, if you're willing to risk that, you can >> just do the job without generics -- just use a regular container >> and cast when you take an object out of it, the way you used to >> do before generics were added. > > But that means that instead of having a remote risk of a run-time > exception, you're completely abandoning type-safety. Yeah, but it seems the middle ground is unacceptable. Either stone- age casting or "the one true way" of implementing generics. Covariance can get in the "unimplementable and to-be-ignored" line with multiple inheritance. -- Marco Von Ballmoos http://earthli.com - Home of the earthli WebCore; PHP web sites made simple.
From: David Cantrell Date: 12:51 on 09 Apr 2008 Subject: Re: Java's anonymous inner classes On Tue, Apr 08, 2008 at 09:36:21PM +0200, Marco Von Ballmoos wrote: > On Apr 7, 2008, at 09:28, Yossi Kreinin wrote: > >I think that the only reasonable test for "is Y a subclass of X?" > >is "can I substitute Y objects whenever X objects are used?". > I agree with the test of "can I substitute Y objects whenever X > objects are used?" I don't. Subclasses can, as well as adding methods, over-ride methods in incompatible ways. Consider this: a GothMusic is-a ModernMusic is-a Music Music defines a few methods, including getmood() which throws an exception if you haven't already setmood(). ModernMusic defines a few extra methods to do with electrickery and amplification, but inherits Music's getmood() and setmood() unchanged. GothMusic inherits from ModernMusic (it needs all the electrickery and amplification) and also supplies its own version of getmood (which always returns "suicidal") and setmood (which throws an exception unless you tell it to be suicidal). GothMusic and ModernMusic are not interchangeable.
From: Marco Von Ballmoos Date: 20:01 on 09 Apr 2008 Subject: Re: Java's anonymous inner classes On Apr 9, 2008, at 13:51, David Cantrell wrote: > On Tue, Apr 08, 2008 at 09:36:21PM +0200, Marco Von Ballmoos wrote: >> Consider this: > > a GothMusic is-a ModernMusic is-a Music > > Music defines a few methods, including getmood() which throws an > exception if you haven't already setmood(). ModernMusic defines a few > extra methods to do with electrickery and amplification, but inherits > Music's getmood() and setmood() unchanged. > > GothMusic inherits from ModernMusic (it needs all the electrickery and > amplification) and also supplies its own version of getmood (which > always returns "suicidal") and setmood (which throws an exception > unless > you tell it to be suicidal). > > GothMusic and ModernMusic are not interchangeable. Good point. Tough to prevent, though. Design-by-Contract provides restrictions on how pre- and postconditions can be added in derived methods, but you can still just throw an exception anywhere. Java has its checked exceptions, but it can cause be a lot of work maintaining all of the declared exceptions -- and a RuntimeException can be thrown at any time. -- Marco Von Ballmoos http://earthli.com - Home of the earthli WebCore; PHP web sites made simple.
From: Adam Atlas Date: 23:34 on 04 Apr 2008 Subject: Re: Java's anonymous inner classes I've hardly used Java, and I had never heard of this feature (?) before, but I didn't have to read any more than the subject line before knowing that I hated it.
From: numien Date: 01:37 on 06 Apr 2008 Subject: Re: Java's anonymous inner classes Simon Wistow wrote: > because that doesn't make sense. So what you have to do is > > > Foo foo; > try { > foo = FooFactory.getFoo(); > runBar(foo); > } catch (SomeCommonException e) { > System.err.println("Got an exception: "+e); > } finally { > FooFactory.release(foo); > } > > public void runBar(final Foo foo) { > Bar.doSomething(new BarRunner() { > public void quux() { > foo.execute(); > } > }); > } > > > > And people wonder why Java has a reputation as being verbose? > And it a *lot* more verbose if "FooFactory.release(foo);" has a chance of throwing an exception... say, if it were a JDBC "Connection.close()" method call.
Generated at 10:27 on 16 Apr 2008 by mariachi