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 / August 2007

Tip: Looking for answers? Try searching our database.

what do you mean I can't (someObj instanceof MyGenericType) ?

Thread view: 
Sideswipe - 10 Aug 2007 18:36 GMT
So, a colleague of mine recently is trying to use generics to enforce
type-correctness (good) in an interface method that takes object. He
needs a specific subtype and so we try this:

public void someMethod(Object myType)

if(SomeGeneric instanceof MyType) ... // compile error

if(SomeGeneric.class.isAssignableFrom(MyType.class)) // compile error

SomeGeneric var = null;

try {
   var = (SomeGeneric)myType; // compiles, and works as expected.

}
catch(ClassCastException cce) {
  // invalid type, ignore
}

If Generics are a type substitution and erase, no matter WHAT type
'SomeGeneric' is from is MUST has '.class' and work with 'instanceof'

I don't get why those fail. Can someone explain?
Mark Rafn - 10 Aug 2007 20:32 GMT
>So, a colleague of mine recently is trying to use generics to enforce
>type-correctness (good) in an interface method that takes object. He
>needs a specific subtype and so we try this:

I don't see any generics in your example.

>public void someMethod(Object myType)
>if(SomeGeneric instanceof MyType) ... // compile error
>if(SomeGeneric.class.isAssignableFrom(MyType.class)) // compile error

You're already confusing me with names - myType isn't a type, it's an object
reference.  I have no idea what SomeGeneric is, and you don't tell me the
compile errors, so I can't guess what you're trying to do.  

A small self-contained code sample, and actual error messages would help a
lot.
--
Mark Rafn    dagon@dagon.net    <http://www.dagon.net/>
Sideswipe - 10 Aug 2007 21:43 GMT
if(T instanceof arg) ... // compile error

if(T.class.isAssignableFrom(arg.getClass())) // compile error

public interface I {
 public void method1(Object arg);
}

public class C<T> implements I {
 public void method1(Object arg);
   // If arg is of type T, use it, otherwise ignore it
   // Note: I can't use T.class to compare because T doesn't exist at
runtime
   T var = null;
   try {
     var = (T)arg;
   }
   catch (ClassCastException e) {
    return;
   }

   ... some more code here
 }
}

Is this better?
Mark Rafn - 10 Aug 2007 23:04 GMT
>if(T instanceof arg) ... // compile error

Right.  T doesn't exist at runtime, only at compile.  

>if(T.class.isAssignableFrom(arg.getClass())) // compile error

Here too.  The type parameter T can't be used except for compile-time checking
and shortcuts.

>public interface I {
>  public void method1(Object arg);
[quoted text clipped - 4 lines]
>    // If arg is of type T, use it, otherwise ignore it
>    // Note: I can't use T.class to compare because T doesn't exist at runtime

There is no runtime type T.  In other words, you cannot make a runtime
choice based on whether an object is type T.

>    T var = null;
>    try {
>      var = (T)arg;

This will generate a warning "[unchecked] unchecked cast" so you know that the
cast isn't actually doing anything.

>    }
>    catch (ClassCastException e) {
[quoted text clipped - 4 lines]
>  }
>}

>Is this better?

Clearer, but you're trying to do something that type erasure prevents you from
doing.  Depending on your object model, you might prefer to have two different
methods rather than (or in addition to, if you have cases where it's needed)
generics.

Have multiple methods method1(Foo arg), method1(Bar arg), which each behave
correctly for their arg.
--
Mark Rafn    dagon@dagon.net    <http://www.dagon.net/>
Joshua Cranmer - 10 Aug 2007 23:10 GMT
> if(T instanceof arg) ... // compile error

arg is a variable not a typename.

> if(T.class.isAssignableFrom(arg.getClass())) // compile error

What is 'T.class'? At runtime, the type argument is statically compiled
into the class file.

>       var = (T)arg;

Is this even legal?

> Is this better?

No. Not by a long shot.

When one needs to work with generics, one ends up working with Class
objects a lot. Your class again:

class C<T> implements I {
    private Class<T> tClass;
    public C(Class<T> tClass) {
        this.tClass = tClass;
    }

    public void method1(Object arg) {
        T var = tClass.cast(arg);
        // [...]
    }
}

Even better would be to make your interface generic as well, so that
less runtime checks would be needed.

Java Generics are NOT C++ Templates. Only one class file is ever used,
so the types of type arguments are erased to the tightest bound known,
which is generally Object. Because each invocation of T is more or less
are equivalent to Object (or the relevant type erasure), constructs like
 T[], T.class, (T), and instanceof T are prohibited.

For more information, read Sun's generics information (look at one of
the more recent generics threads for the link; I don't know it off the
top of my head).

Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Ben Phillips - 11 Aug 2007 23:15 GMT
> Because each invocation of T is more or less
> are equivalent to Object (or the relevant type erasure), constructs like
>  T[], T.class, (T), and instanceof T are prohibited.

Not quite. (T) is permitted but gives the "unchecked" warning. If you
are in say "class Bar <T extends Foo>" a cast like (T) ends up checking
only that the thing is a Foo. Quite often Foo is Object and then it
checks nothing, of course.

There's some way to suppress those warnings but it's usually a sign of a
broken design if you get the urge to do so. Try to find another way to
do what you want to do in a type-safe manner. It will usually involve a
Class<T>.
Danno - 10 Aug 2007 23:22 GMT
> if(T instanceof arg) ... // compile error

public static <T> void  testElement(T t) {
       if (t instanceof String) {
           System.out.println("t is a String");
       }
   }

Yeah that works
> if(T.class.isAssignableFrom(arg.getClass())) // compile error

Looks like that works too.
if(t.getClass().isAssignableFrom(String.class))
System.out.println("Weee");

> public interface I {
>   public void method1(Object arg);
[quoted text clipped - 18 lines]
>
> }

public class C<T> {
   public void method1(T arg) { //arg is of type T
       //There is no need to test.  T
       //  is going be what you declare for in the first place.
   }
}
Danno - 10 Aug 2007 23:03 GMT
> So, a colleague of mine recently is trying to use generics to enforce
> type-correctness (good) in an interface method that takes object. He
[quoted text clipped - 22 lines]
>
> I don't get why those fail. Can someone explain?

You can only do instance tests on reified types. A reified type is a
type that has runtime representation. Including raw types, type
variables (like T), Parameterized types with actual parameters, etc.


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



©2008 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.