You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Leo Sutic <le...@inspireinfrastructure.com> on 2004/01/28 16:11:39 UTC

Java 1.5, fun with lookups and generics

All,

we all hate the:

    MyComponent comp = (MyComponent) lookup (MyComponent.ROLE);

idiom. A typecast, and just too much typing to be fun.

I downloaded the JDK1.5 preview today, and wrote this:

    interface ServiceManager {
        public <T> T lookup (String key) throws Exception;
        public void release (Object o);
    }

    class DefaultServiceManager implements ServiceManager {
        public <T> T lookup (String key) throws Exception {
            Object o = doGet (key);
            try {
                return (T) o; // unchecked cast to type T here, should
be fine.
            } catch (Throwable t) {
                return null;
            }
        }

        private Object doGet (String key) {
            if (key.equals ("A")) return new A();
            if (key.equals ("B")) return new B();
            return null;
        }

        public void release (Object o) {};
    }

    class A {}
    class B {}

    public class MyClass {

        public static void main(String[] args) throws Exception {
            ServiceManager sm = new DefaultServiceManager();
            A a = sm.<A>lookup ("A");
            B b = sm.<B>lookup ("B");
            System.out.println (a);
            System.out.println (b);
        }
    }

Resulting in:

    A@7d772e
    B@11b86e7

Due to the type erasure mechanism used in 1.5, you can't select from a 
type variable, but I understand that we're decoupling the lookup
key from the interface name anyway:

    public <T> T lookup () throws Exception {
        return (T) doLookup (T.ROLE); // T.ROLE is not a valid construct
    }

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Jonathan Hawkes <jh...@adsnm.com>.
> > You're still casting.  You're just postponing it a little.
>
> The purpose of this isn't to eliminate casts altogether - I don't
> see how that can be possible given that we are dealing with
> types (the component instances) that aren't known at compile-time.

Agreed.

>
> But:
>
> > DefaultServiceManager.lookup does a cast to type T.
>
> And that is the good part of this: We got the casting out of the
> client code and put it in the container code. This means that
> the client will be a bit more compile-time checked at the cost
> of the container being a little less compile-time checked. Since
> the container is considered to be the most-tested of those two
> codebases (due to it being common code used by many people),
> this tradeoff makes sense.

I see your point.  However, it still doesn't make the code any easier to
type or any prettier :)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Java 1.5, fun with lookups and generics

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Jonathan Hawkes [mailto:jhawkes@adsnm.com] 
> 
> You're still casting.  You're just postponing it a little. 

The purpose of this isn't to eliminate casts altogether - I don't
see how that can be possible given that we are dealing with
types (the component instances) that aren't known at compile-time.

But:

> DefaultServiceManager.lookup does a cast to type T.

And that is the good part of this: We got the casting out of the
client code and put it in the container code. This means that
the client will be a bit more compile-time checked at the cost
of the container being a little less compile-time checked. Since
the container is considered to be the most-tested of those two
codebases (due to it being common code used by many people),
this tradeoff makes sense.

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Jonathan Hawkes <jh...@adsnm.com>.
You're still casting.  You're just postponing it a little.
DefaultServiceManager.lookup does a cast to type T.  You specified what type
T is in MyClass.main.  It is perhaps possible that DefaultServiceManager
could be implemented without casting (using further generics), but off the
top of my head I can't see how.

<snip>

    interface ServiceManager {
        public <T> T lookup (String key) throws Exception;
        public void release (Object o);
    }

    class DefaultServiceManager implements ServiceManager {
        public <T> T lookup (String key) throws Exception {
            Object o = doGet (key);
            try {
                return (T) o; // unchecked cast to type T here, should be
fine.
            } catch (Throwable t) {
                return null;
            }
        }

        private Object doGet (String key) {
            if (key.equals ("A")) return new A();
            if (key.equals ("B")) return new B();
            return null;
        }

        public void release (Object o) {};
    }

    class A {}
    class B {}

    public class MyClass {

        public static void main(String[] args) throws Exception {
            ServiceManager sm = new DefaultServiceManager();
            A a = sm.<A>lookup ("A");
            B b = sm.<B>lookup ("B");
            System.out.println (a);
            System.out.println (b);
        }
    }

</snip>

----- Original Message ----- 
From: "Leo Sutic" <le...@inspireinfrastructure.com>
To: "'Avalon Developers List'" <de...@avalon.apache.org>
Sent: Wednesday, January 28, 2004 11:18 AM
Subject: RE: Java 1.5, fun with lookups and generics


>
>
> > From: Jonathan Hawkes [mailto:jhawkes@adsnm.com]
> >
> > It just looks like a belayed cast to me.
>
> What do you mean by that?
>
> /LS
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Java 1.5, fun with lookups and generics

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Jonathan Hawkes [mailto:jhawkes@adsnm.com] 
> 
> It just looks like a belayed cast to me.

What do you mean by that?

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Jonathan Hawkes <jh...@adsnm.com>.
It just looks like a belayed cast to me.

----- Original Message ----- 
From: "Niclas Hedhman" <ni...@hedhman.org>
To: <de...@avalon.apache.org>
Sent: Wednesday, January 28, 2004 9:56 AM
Subject: Re: Java 1.5, fun with lookups and generics


> Leo Sutic said:
> > we all hate the:
> >
> >     MyComponent comp = (MyComponent) lookup (MyComponent.ROLE);
> 
> >     ServiceManager sm = new DefaultServiceManager();
> >     A a = sm.<A>lookup ("A");
> 
> MyComponent comp = sm.<MyComponent>lookup( "MyComponent" );
> 
> 
> And that would be compile time checkable???
> 
> The construct, IMHO, does not look any "nicer", so it'd better be
> compile time type safe... (even though I fail to see how :o(  )
> 
> Niclas
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Wednesday 28 January 2004 10:55, Leo Sutic wrote:
> > From: Niclas Hedhman [mailto:niclas@hedhman.org]
> >  A a = sm.<A>lookup ("B");
> >
> > How would the compiler know?
>
> OK, *that* is something that can't be statically checked. The upside is
> that
> we've isolated the *only* part that can't be statically checked, and
> we've isolated it in the container:

A a = sm.<A>lookup ("B");
A a = (A) sm.lookup ("B");

So where is the famous difference. I don't care if I get a ClassCastException 
on this line, or the cast in the ServiceManager.

More interestingly though, what about;

A a = sm.<A>lookup();

Can the ServiceManager do the equivalent of 
   Class c = T.class;

So that Merlin could lookup a proper type without argument in the lookup?

That would be nice! (Although it may be years away before we can do it.)

Niclas

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Wednesday 28 January 2004 11:23, Leo Sutic wrote:
> The type parameter T gets "erased" so *at runtime*, T = Object.
> This makes your test:
>
>     if (o instanceof Object) {
>         return o;
>     } else {
>         throw new StupidAvalonProgrammerException();
>     }

Why does Sun make a half-baked effort out of it??

Instead of introducing this "PoBS", why not do it runtime supported and call 
it Java3 or Java2 Ver 2.0  (whatever). Now we will get another mechanism that 
will be raped by the programmers, making a lot of the code even harder to 
read and understand. I am not happy about this.

Niclas

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Jonathan Hawkes <jh...@adsnm.com>.
You can skip it.

----- Original Message ----- 
From: "Niclas Hedhman" <ni...@hedhman.org>
To: "Avalon Developers List" <de...@avalon.apache.org>
Sent: Wednesday, January 28, 2004 12:37 PM
Subject: Re: Java 1.5, fun with lookups and generics


> On Wednesday 28 January 2004 11:38, Jonathan Hawkes wrote:
> > >     MyComponent comp = sm.lookup (MyComponent.class, "MyComponent");
> >
> > I like that.
>
> Didn't Leo forgot the Template??
>
> MyComponent comp = sm.<MyComponent>lookup (MyComponent.class,
"MyComponent");
>
> Or would it really be possible to skip?
>
> Niclas
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Java 1.5, fun with lookups and generics

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Niclas Hedhman [mailto:niclas@hedhman.org] 
> 
> On Wednesday 28 January 2004 11:38, Jonathan Hawkes wrote:
> > >     MyComponent comp = sm.lookup (MyComponent.class, 
> "MyComponent");
> >
> > I like that.
> 
> Didn't Leo forgot the Template??
> 
> MyComponent comp = sm.<MyComponent>lookup (MyComponent.class, 
> "MyComponent");
> 
> Or would it really be possible to skip?

The template argument is inferred from the MyComponent.class 
parameter.

The reason you needed the explicit <MyComponent> in the other
example is because it couldn't be inferred from any of the
arguments.

Note: The compiler must know the type of the argument to
perform inference. Thus this does ***not*** work:

    Class c = MyComponent.class;
    MyComponent comp = sm.lookup (c, "MyComponent");

This, however, does:

    Class<MyComponent> c = MyComponent.class;
    MyComponent comp = sm.lookup (c, "MyComponent");

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Wednesday 28 January 2004 11:38, Jonathan Hawkes wrote:
> >     MyComponent comp = sm.lookup (MyComponent.class, "MyComponent");
>
> I like that.

Didn't Leo forgot the Template??

MyComponent comp = sm.<MyComponent>lookup (MyComponent.class, "MyComponent");

Or would it really be possible to skip?

Niclas

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Jonathan Hawkes <jh...@adsnm.com>.
> What you have to do is:
> 
>     public <T> T lookup (Class<T> expectedClass, String key) throws
> Exception {
>         Object o = doGet (key);
>         if (expectedClass.isAssignableFrom (o.getClass ())) {
>             return (T) o; // checked cast to type T here
>         } else {
>             throw new StupidAvalonProgrammerException();
>         }                
>     }
> 
> And use it client-side like this:
> 
>     MyComponent comp = sm.lookup (MyComponent.class, "MyComponent");

I like that.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Java 1.5, fun with lookups and generics

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> -----Original Message-----
> From: Jonathan Hawkes [mailto:jhawkes@adsnm.com] 
> Sent: den 28 januari 2004 20:08
> To: Avalon Developers List
> Subject: Re: Java 1.5, fun with lookups and generics
> 
> 
> > OK, *that* is something that can't be statically checked. 
> The upside 
> > is that we've isolated the *only* part that can't be statically 
> > checked, and we've isolated it in the container:
> >
> >             try {
> >                 return (T) o; // unchecked cast to type T 
> here, should 
> > be fine.
> >             } catch (Throwable t) {
> >                 return null;
> >             }
> >
> > /LS
> 
> So, in the container code, we could have something like this:
> 
> if (o instanceof T) {
>     return o;
> } else {
>     throw new StupidAvalonProgrammerException(); // instead 
> of ClassCastException }

Something like that - except you can't do that.

The type parameter T gets "erased" so *at runtime*, T = Object.
This makes your test:

    if (o instanceof Object) {
        return o;
    } else {
        throw new StupidAvalonProgrammerException();
    }

What you have to do is:

    public <T> T lookup (Class<T> expectedClass, String key) throws
Exception {
        Object o = doGet (key);
        if (expectedClass.isAssignableFrom (o.getClass ())) {
            return (T) o; // unchecked cast to type T here, should be
fine.
        } else {
            throw new StupidAvalonProgrammerException();
        }                
    }

And use it client-side like this:

    MyComponent comp = sm.lookup (MyComponent.class, "MyComponent");

You can also use a helper method for the cases when 
key == expectedClass.getName ():

    public <T> T lookup (Class<T> expectedClass) throws Exception {
        return lookup (expectedClass, expectedClass.getName ());
    }

And write:

    MyComponent comp = sm.lookup (MyComponent.class);

(Everyone confused yet, or shall I have another go at it?)

/LS



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Jonathan Hawkes <jh...@adsnm.com>.
> OK, *that* is something that can't be statically checked. The upside is
> that
> we've isolated the *only* part that can't be statically checked, and
> we've isolated it in the container:
>
>             try {
>                 return (T) o; // unchecked cast to type T here, should
> be fine.
>             } catch (Throwable t) {
>                 return null;
>             }
>
> /LS

So, in the container code, we could have something like this:

if (o instanceof T) {
    return o;
} else {
    throw new StupidAvalonProgrammerException(); // instead of
ClassCastException
}


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Java 1.5, fun with lookups and generics

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Niclas Hedhman [mailto:niclas@hedhman.org] 
> 
> On Wednesday 28 January 2004 10:06, Leo Sutic wrote:
> > > From: Niclas Hedhman [mailto:niclas@hedhman.org]
> > > And that would be compile time checkable???
> >
> > Yes.
> 
> > Given:
> >     public <T> T lookup (String key) throws Exception;
> > an instantiation specified as:
> >     sm.<MyComponent>lookup( ... )
> > that is, with T = MyComponent, will be:
> >     public MyComponent lookup (String key) throws Exception;
> 
> How is that possible? Given;
> 
>         private Object doGet (String key) {
>             if (key.equals ("A")) return new A();
>             if (key.equals ("B")) return new B();
>             return null;
>         }
> 
>  A a = sm.<A>lookup ("B");
> 
> How would the compiler know?

OK, *that* is something that can't be statically checked. The upside is
that
we've isolated the *only* part that can't be statically checked, and
we've isolated it in the container:

            try {
                return (T) o; // unchecked cast to type T here, should
be fine.
            } catch (Throwable t) {
                return null;
            }

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Wednesday 28 January 2004 10:06, Leo Sutic wrote:
> > From: Niclas Hedhman [mailto:niclas@hedhman.org]
> > And that would be compile time checkable???
>
> Yes.

> Given:
>     public <T> T lookup (String key) throws Exception;
> an instantiation specified as:
>     sm.<MyComponent>lookup( ... )
> that is, with T = MyComponent, will be:
>     public MyComponent lookup (String key) throws Exception;

How is that possible? Given;

        private Object doGet (String key) {
            if (key.equals ("A")) return new A();
            if (key.equals ("B")) return new B();
            return null;
        }

 A a = sm.<A>lookup ("B");

How would the compiler know?


Niclas



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Java 1.5, fun with lookups and generics

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Niclas Hedhman [mailto:niclas@hedhman.org] 
> 
> Leo Sutic said:
> > we all hate the:
> >
> >     MyComponent comp = (MyComponent) lookup (MyComponent.ROLE);
> 
> >     ServiceManager sm = new DefaultServiceManager();
> >     A a = sm.<A>lookup ("A");
> 
> MyComponent comp = sm.<MyComponent>lookup( "MyComponent" );
> 
> 
> And that would be compile time checkable???

Yes.

> The construct, IMHO, does not look any "nicer", so it'd 
> better be compile time type safe... (even though I fail to 
> see how :o(  )

Given:

    public <T> T lookup (String key) throws Exception;

an instantiation specified as:

    sm.<MyComponent>lookup( ... )

that is, with T = MyComponent, will be:

    public MyComponent lookup (String key) throws Exception;

which gives you all the safety you may want.

If you can guarantee that the lookup key == the expected interface name,
then:

    public <T> T lookup (Class<T> expectedClass) throws Exception;

allows you to use inference and write:

    MyComponent comp = sm.lookup( MyComponent.class );

which will map T to MyComponent, as above, and pass the class
to the method.

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Java 1.5, fun with lookups and generics

Posted by Niclas Hedhman <ni...@hedhman.org>.
Leo Sutic said:
> we all hate the:
>
>     MyComponent comp = (MyComponent) lookup (MyComponent.ROLE);

>     ServiceManager sm = new DefaultServiceManager();
>     A a = sm.<A>lookup ("A");

MyComponent comp = sm.<MyComponent>lookup( "MyComponent" );


And that would be compile time checkable???

The construct, IMHO, does not look any "nicer", so it'd better be
compile time type safe... (even though I fail to see how :o(  )

Niclas



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org