From: Robert Klemme on
On 10.07.2010 02:54, markspace wrote:
> Lew wrote:
>
>> try
>> {
>> // ClassCastException caught so this is safe
>> @SuppressWarnings( "unchecked" )
>> Class <Authenticator> clazz =
>> (Class <Authenticator>) Class.forName( name );
>>
>> authenticator = clazz.newInstance();
>> }
>
>
> The following doesn't generate any warning messages and doesn't require
> a @SuppressWarnings annotation. It's also a tad shorter. It will throw
> ClassCastException if the type loaded isn't right, but that could be
> caught too. I'm not sure it's better, but it is an alternative.
>
> try
> {
> Class<?> c = Class.forName( "test" );
> SomeType s = (SomeType) c.newInstance();
>
> } catch( InstantiationException ex ) { ... // etc.

This is even better because you don't even need a cast:

public static Authenticator create1(String className) throws
CreationException {
try {
final Class<? extends Authenticator> cl =
Class.forName(className).asSubclass(Authenticator.class);
return cl.newInstance();
} catch (ClassNotFoundException e) {
throw new CreationException("Class not found: " + className, e);
} catch (InstantiationException e) {
throw new CreationException("Could not create instance: " +
className, e);
} catch (IllegalAccessException e) {
throw new CreationException("Operation not permitted", e);
}
}

You can even pack it in one line and it doesn't look too ugly:

public static Authenticator create2(String className) throws
CreationException {
try {
return
Class.forName(className).asSubclass(Authenticator.class).newInstance();
} catch (ClassNotFoundException e) {
throw new CreationException("Class not found: " + className, e);
} catch (InstantiationException e) {
throw new CreationException("Could not create instance: " +
className, e);
} catch (IllegalAccessException e) {
throw new CreationException("Operation not permitted", e);
}
}

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
From: markspace on
Robert Klemme wrote:

>
> This is even better because you don't even need a cast:

> final Class<? extends Authenticator> cl =
> Class.forName(className).asSubclass(Authenticator.class);


Interesting. Although "asSubclass(Class<?>)" is a cast and the
documentation even says "Casts this Class object to represent a subclass
of...." It will throw ClassCastException if the named class is not a
type of Authenticator, which should be caught, imo, because you probably
want to provide a better error mechanism that just halting.

Definitely more than one way to do it, I agree.
From: Daniel Pitts on
On 7/9/2010 6:49 PM, Arne Vajh�j wrote:
> On 09-07-2010 20:13, Arne Vajh�j wrote:
>> On 09-07-2010 19:07, Simon Brooke wrote:
>>> OK, here's a problem which many people must have encountered, and there
>>> must be a 'best practice' solution.
>>>
>>> I have a thing which is configurable by plugging other things into it.
>>> Obviously the other things I plug in must conform to specific
>>> interfaces,
>>> but what thing I actually plug in is determined at run-time by reading
>>> the name of the plugin class from a configuration file. An example (in
>>> Java 1.4) is as follows:
>>>
>>> 1 String v = config.getValueAsString( "authenticator_class");
>>> 2
>>> 3 if (v != null) {
>>> 4 Class authenticatorClass;
>>> 5
>>> 6 try {
>>> 7 authenticatorClass = Class.forName( v);
>>> 8 } catch (ClassNotFoundException c) {
>>> 9 throw new InitialisationException(
>>> 10 "Could not find class [" + v
>>> 11 + "]", c);
>>> 12 }
>>> 13
>>> 14 try {
>>> 15 authenticator =
>>> 16 (Authenticator) authenticatorClass
>>> 17 .newInstance();
>>> 18 } catch (ClassCastException e) {
>>> 19 throw new InitialisationException(
>>> 20 "Not a valid authenticator class", e);
>>> 21 } catch (InstantiationException f) {
>>> 12 throw new InitialisationException(
>>> 23 "Could not instantiate authenticator", f);
>>> 24 }
>>> 25 }
>>>
>>> Obviously one can vacuously 'bring this up to date' by changing line
>>> 4 to
>>>
>>> 4 Class<?> authenticatorClass;
>>>
>>> but I feel that the right thing to do must surely be to use
>>>
>>> 4 Class<Authenticator> authenticatorClass;
>>> 5
>>> 6 try {
>>> 7 authenticatorClass =
>>> (Class<Authenticator>) Class.forName( v);
>>> 8 } catch (Exception e) {
>>>
>>> then if the class specified did not inherit from Authenticator a
>>> ClassCastException would be caught at line 8, and the second try/catch
>>> block might become redundant. However, if I do that, Java 1.6 gives me a
>>> warning at line 7:
>>>
>>> 'Type safety: Unchecked cast from Class<capture#1-of ?> to
>>> Class<Authenticator>'
>>>
>>> Eclipse offers to fix this by adding an @SuppressWarnings clause, but
>>> I'm
>>> not sure I want to suppress warnings...
>>>
>>> What is the preferred pattern in Java 1.5/1.6, and why?
>>
>> Have you tried:
>>
>> authenticatorClass = Class<Authenticator>.forName( v);
>>
>> ?
>
> I just did myself.
>
> It does not compile.

forName returns a Class<?> only, you can not ask it to do otherwise.
You might be able to do:
Class.forName(v).asSubclass(Authenticator.class);

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Christian Kaufhold on
markspace <nospam(a)nowhere.com> wrote:

> Lew wrote:
>
>> try
>> {
>> // ClassCastException caught so this is safe
>> @SuppressWarnings( "unchecked" )
>> Class <Authenticator> clazz =
>> (Class <Authenticator>) Class.forName( name );
>>
>> authenticator = clazz.newInstance();
>> }
>
>
> The following doesn't generate any warning messages and doesn't require
> a @SuppressWarnings annotation. It's also a tad shorter. It will throw
> ClassCastException if the type loaded isn't right, but that could be
> caught too. I'm not sure it's better, but it is an alternative.
>
> try
> {
> Class<?> c = Class.forName( "test" );
> SomeType s = (SomeType) c.newInstance();

Do never use Class.newInstance(), it will pass through /any/ Throwable
that the actual code throws (it is actually one way to throw a checked exception
that is not declared). Instead use the explicit no-argument Constructor.

Strictly speaking, if a reflectively invoked method throws InterruptedException
(wrapped in the InvocationTargetException), one should also interrupt the current
Thread (or pass the InterruptedException on), as otherwise the interruption is
swallowed.