Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / February 2006

Tip: Looking for answers? Try searching our database.

Generics and forName()

Thread view: 
Jacob - 31 Jan 2006 08:32 GMT
If I have this class:

  class A {
    public A(String a);
  }

Is it possible to make an instance through reflection without getting a
compiler warning (java 1.5)?

The following gives an unchecked warning in the first line due to the
forced cast. Using "?" just postpone the the problem:

  Class<A> clazz = (Class<A>) Class.forName("A");
  Constructor<A> ctor = clazz.getConstructor(String.class);
  A a = ctor.newInstance("hello world");

The problem is that in my organization we treat warnings as errors and
the above simply isn't doable within such a regime.

What is the workaround?

(And why whould all the above be possible (by Class<?> and Class.newInstance()),
if just the constructor didn't take any arguments?)

Thanks!
Tony Morris - 31 Jan 2006 00:31 GMT
> If I have this class:
>
[quoted text clipped - 21 lines]
>
> Thanks!

Hello Jacob,
I have seen this question quite a number of times, which prompted me to add
it to my FAQ.
http://jqa.tmorris.net/GetQAndA.action?qids=80&showAnswers=true

I have also included a code sample below that demonstrates what you want to
achieve.
As a note, if you have a policy of not being permitted to have compile-time
warnings, it may be in your interest to learn about generics.

Also note that there are some valid use cases that force a compile-time
warning, due to the contrived nature of the Java generics implementation, so
you may seek to have this policy reviewed. These forced use cases are the
result of the introduction of failure to maintain a conversion between
arrays and parameterised types (without a warning) - as an example, take a
look at the java.util.ArrayList implementation, which is backed by an
array - you will note that there is a forced compile-time warning. You
discover these nitty details when you implement the spec. after a JSR
"expert" group has been onto the case :) I did make this issue known well
before the spec. was released, but the most plausible response I got was
"oops".

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import static java.lang.Class.forName;

class X
{
   X(final String s)
   {

   }
}

final class Main
{
   private Main() throws UnsupportedOperationException
   {
       throw new UnsupportedOperationException();
   }

   public static void main(final String... args) throws
       ClassNotFoundException,
       NoSuchMethodException,
       InstantiationException,
       IllegalAccessException,
       InvocationTargetException
   {
       final Class<?> c = forName("X");
       final Class<? extends X> xc = c.asSubclass(X.class);
       final Constructor<? extends X> ctor =
xc.getConstructor(String.class);
       final X x = ctor.newInstance(args[0]);
   }
}

--
Tony Morris
http://tmorris.net/

Java Questions and Answers
http://jqa.tmorris.net/
Chris Uppal - 31 Jan 2006 11:42 GMT
> The problem is that in my organization we treat warnings as errors and
> the above simply isn't doable within such a regime.

Ha ha!  Then you loose!

I'm not sure about the particular example you mention -- I don't know a
(working) way to avoid the warning myself, but that doesn't mean there isn't
one[*].

But the real problem here is not javac, but the way your organisation works.
Find the person responsible for this absurd rule and fire him/her (and,
perhaps, also his/her manager).  Or if the condition was imposed by a customer,
find the salesthing which accepted that clause in the contract and fire it.

   -- chris

[*] Well, I suppose you could compile with -source 1.4
Roedy Green - 31 Jan 2006 13:43 GMT
>The following gives an unchecked warning in the first line due to the
>forced cast. Using "?" just postpone the the problem:
>
>   Class<A> clazz = (Class<A>) Class.forName("A");
>   Constructor<A> ctor = clazz.getConstructor(String.class);
>   A a = ctor.newInstance("hello world");

Unchecked means the compiler cannot guarantee safety at compile time.
The truth is it can't. It has absolutely no idea what A will be/do. If
you want the compiler to be able to check, it wants to see the code at
compile time.

Further this code makes no sense to me. If type A is known at compile
time, why are you dicking around with Class.forName. You only do that
when you DON'T know the class name, just an interface it implements..
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Ian Pilcher - 31 Jan 2006 15:12 GMT
> If I have this class:
>
[quoted text clipped - 14 lines]
> The problem is that in my organization we treat warnings as errors and
> the above simply isn't doable within such a regime.

In this case, you can use Class.asSubclass:

   Class<A> clazz = Class.forName("A").asSubclass(A.class);

As Tony pointed out, there are perfectly valid (and sometimes
unavoidable) constructs which will produce unchecked cast warnings.
Read up on the @SuppressWarnings annotation, and note that Sun's
compiler didn't support it until 1.5.0_06.

I'm assuming that the code you posted is a contrived example.  If not,
Roedy's comment is right on; there's no reason to use Class.forName for
a known type.

HTH

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

Jacob - 01 Feb 2006 06:53 GMT
> If I have this class:
>
>   class A {
>     public A(String a);
>   }

As pointed out, a better example should be

  class A implements B {
    public A(String a);
  }

  Class<A> clazz = (Class<A>) Class.forName("A");
  Constructor<A> ctor = clazz.getConstructor(String.class);
  B b = ctor.newInstance("hello world");

Though I may understand *why* the compiler complains, I
have a feeling that a warning from the compiler is a strong
hint to modify the code so that the warning disappears.
What use has a warning if it is always there? But I guess
it boils down to the definition of the term "warning", and I
might be influenced by past (and present) experience with
C/C++ compilers as Chris suggests.

But my second question was not adressed. Why doesn't the
compiler complain in this case:

  class A implements B {
    public A();
  }

  Class<?> clazz = Class.forName("A");
  B b = (B) clazz.newInstance();  // Why is this safe?

Thanks!
Chris Uppal - 01 Feb 2006 10:06 GMT
> But my second question was not adressed. Why doesn't the
> compiler complain in this case:
[quoted text clipped - 5 lines]
>    Class<?> clazz = Class.forName("A");
>    B b = (B) clazz.newInstance();  // Why is this safe?

It seems to be because the compiler doesn't warn (or doesn't warn as often ?)
about casts to interfaces.  When you are casting the result of Class.forName()
you are casting to a concrete type, and the compiler whinges about it.  It
seems to think that mistakes are less likely with casts to interfaces (why ??).
For instance the following compiles without complaint:

 Object o = new A("hello")
 B b = (B) o;

Kind of arbitrary...  (Which rather nicely illustrates my earlier point ;-)

   -- chris
Thomas Hawtin - 01 Feb 2006 10:30 GMT
>>    class A implements B {

>>    B b = (B) clazz.newInstance();  // Why is this safe?
>
> It seems to be because the compiler doesn't warn (or doesn't warn as often ?)
> about casts to interfaces.  When you are casting the result of Class.forName()
> you are casting to a concrete type, and the compiler whinges about it.  It
> seems to think that mistakes are less likely with casts to interfaces (why ??).

I don't think it makes any difference whether the type is a class or an
interface.

> For instance the following compiles without complaint:
>
>   Object o = new A("hello")
>   B b = (B) o;

In that case, and the case above, you are casting to a type that can be
checked at runtime.

If you cast to a generic parameter type or a generic type then the cast
cannot be checked at runtime, hence the unchecked cast warning.

Some of the java.util code not only uses code that causes unchecked cast
warnings, but really allows a generic parameter type reference to point
to an incorrect type of object.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Chris Uppal - 01 Feb 2006 11:34 GMT
> > For instance the following compiles without complaint:
> >
[quoted text clipped - 3 lines]
> In that case, and the case above, you are casting to a type that can be
> checked at runtime.

No I'm not; 'o' is of declared type Object.

   -- chris
Chris Uppal - 01 Feb 2006 12:00 GMT
I wrote:

> > > For instance the following compiles without complaint:
> > >
[quoted text clipped - 5 lines]
>
> No I'm not; 'o' is of declared type Object.

Sorry, I misread you; you said "runtime", not "compile time".

With that correction, I take your point.

I had not, in fact, realised that the compiler doesn't warn about
   List<Object> list = ...
   A a = (A)list.get(0);

Even more reason to avoid generics ;-)

   -- chris
Tony Morris - 01 Feb 2006 21:57 GMT
> For instance the following compiles without complaint:
>
>   Object o = new A("hello")
>   B b = (B) o;

The misuse/warning of a parameterised type can be roughly interpreted as:
"You opted to use generic type-safety, but circumvented it with a cast - as
a result, I (the compiler) will issue you with a warning". In your above
case, it doesn't hold that you "opted to use generic type-safety",
therefore, you receive no warning.

Of course, you may choose to argue that the premise that I provided above is
somewhat contrived in that it doesn't meet a majority of use cases (or
whatever you might choose), in which case, I offer you the postulation that
you are just "scratching the surface" with respect to the defectiveness of
JSR-14.

Signature

Tony Morris
http://tmorris.net/



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.