Deprecated functionality with generics (previously valid code now invalid)

M

mortoray

We have a library that implements a simple scripting language. Our
implementation appears to have been deprecated by Java 5 and we need
some input on how to make the code compliant. (The code still compiles
and works but it spits out the "unchecked type" warnings, and Sun's
docs seem to indicate this may be disallowed in future versions).

The basic situation:

1) We have a variable map stored in a Map<Object,Object>
2) We have a function called Put which takes an object and puts inside
a Collection stored in the variable map
3) Previously we did this simply as (abbreviated syntax)

void put( String variable, Object data ) {
Object obj = variables.get( variable );
if( !(obj instanceof Collection) )
throw ...;
((Collection)obj).add( data );
}

The caller of the function was responsible for inserting the correct
types into the correct collections. Additionally, the actual type of
the collection is not known, if may be of Numbers, Strings, or just
Objects.

4) With the new Java (5) this causes unchecked type warnings because
"add" uses a generic type in its signature. (We have an equivalent
case with "get", but that works fine since it isn't typed).

Out initial idea was to do the following:

Object obj = variables.get( variable );
if( !(obj instanceof Collection<? extends Object>) )
throw ...;
((Collection<? extends Object>)obj).add( data );

But that just produces two warnings instead of one because you can't
use instanceof with wildcards and the following cast is also converting
from untyped to typed.

This disallowed casting concerns me additionally, since even if we
rewrite the code such that we always know a COllection<Object> is
stored in the variable, it doesn't appear to help, since we still need
to do the cast and get the unchecked warning.

Has this type of functionaly truly been deprecated? Or is there someway
to achieve this without gettnig the warning messages?
 
C

Chris Uppal

This disallowed casting concerns me additionally, since even if we
rewrite the code such that we always know a COllection<Object> is
stored in the variable, it doesn't appear to help, since we still need
to do the cast and get the unchecked warning.

Personally, I'd use this option and live with the warnings about casts.

IMO Sun have overestimated the utility of generics in /eliminating/ run-time
casts (explicit ones in the Java code) and in some future release will have to
correct/reduce or otherwise make sensible the warnings the compiler spits out.

The only way (as far as I can see) that your code can actually stop woking in a
future release is if Sun are willing to throw backwards compatibility out of
the window altogether. (Including at the JVM level).

-- chris
 
A

Adam P. Jenkins

We have a library that implements a simple scripting language. Our
implementation appears to have been deprecated by Java 5 and we need
some input on how to make the code compliant. (The code still compiles
and works but it spits out the "unchecked type" warnings, and Sun's
docs seem to indicate this may be disallowed in future versions).

The basic situation:

1) We have a variable map stored in a Map<Object,Object>
2) We have a function called Put which takes an object and puts inside
a Collection stored in the variable map
3) Previously we did this simply as (abbreviated syntax)

void put( String variable, Object data ) {
Object obj = variables.get( variable );
if( !(obj instanceof Collection) )
throw ...;
((Collection)obj).add( data );
}

The caller of the function was responsible for inserting the correct
types into the correct collections. Additionally, the actual type of
the collection is not known, if may be of Numbers, Strings, or just
Objects.

4) With the new Java (5) this causes unchecked type warnings because
"add" uses a generic type in its signature. (We have an equivalent
case with "get", but that works fine since it isn't typed).

Out initial idea was to do the following:

Object obj = variables.get( variable );
if( !(obj instanceof Collection<? extends Object>) )
throw ...;
((Collection<? extends Object>)obj).add( data );

But that just produces two warnings instead of one because you can't
use instanceof with wildcards and the following cast is also converting
from untyped to typed.

This disallowed casting concerns me additionally, since even if we
rewrite the code such that we always know a COllection<Object> is
stored in the variable, it doesn't appear to help, since we still need
to do the cast and get the unchecked warning.

Has this type of functionaly truly been deprecated? Or is there someway
to achieve this without gettnig the warning messages?

Here's a trick to get rid of the compiler warning messages when you
really do need to cast an Object to a generic type, such as when
deserializing objects, or your example. I keep this utility class around:

public class CastUtils {
public static <T> T cast(Object o) {
return (T)o;
}
}

You'll get an "unchecked cast" warning when compiling the CastUtils
class, but not when you use it, like this:

Object obj = new ArrayList<String>();
// following statement generates no compiler warning
List<String> list = CastUtils.cast(obj);

I think using this is better than just allowing the warning messages,
since in a large project you may end up with too many spurious warnings
to notice the valid ones.

Note: Just keep in mind that the cast method is more dangerous than a
normal cast because it lets you cast any type of object to any other
type. As long as you only use it to cast Object to other types, then
it's no worse than the normal cast.

Adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top