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 / September 2006

Tip: Looking for answers? Try searching our database.

Annoying 1.5 warnings

Thread view: 
aaronfude@gmail.com - 01 Sep 2006 14:54 GMT
Why does the following code cause a warning and how to avoid it w/o
turning warnings off?

Vector<File> a = (Vector<File>) (Object) new Vector<File>();

The warning is:

Type safety: The cast from Object to Vector<File> is actually checking
against the erased type Vector
Robert Klemme - 01 Sep 2006 15:00 GMT
> Why does the following code cause a warning

Because you cast from Object to Vector<File>.

> and how to avoid it w/o
> turning warnings off?

Don't do unnecessary casts up and down the class hierarchy.

> Vector<File> a = (Vector<File>) (Object) new Vector<File>();
>
> The warning is:
>
> Type safety: The cast from Object to Vector<File> is actually checking
> against the erased type Vector

Right it is.

Regards

    robert
Zaph0d - 01 Sep 2006 16:05 GMT
>  > and how to avoid it w/o
> > turning warnings off?
>
> Don't do unnecessary casts up and down the class hierarchy.

Wrong.

> > Vector<File> a = (Vector<File>) (Object) new Vector<File>();

To understand the warning, you need to understand how generics work.
While at compile time generic types are full, meaning Vector<String> is
not Vector<Integer>, at runtime this distinction goes away, meaning
Vector<String> is Vector<Integer>. The process is called erasure and it
is done to remain backward compatible with Java 1.4 jvm (Code with
generics but no other 1.5 features, compiled with jdk 1.5, will run on
jvm 1.4).

How does this affect you?
At compile time you enjoy the generic type safety telling you that
"new Vector<Integer>().add("hi!");" will not work.
But (and there's always a "but"), at runtime there is no way to
distinguish between Vector<String> and Vector<Integer>. That means that
the compiler can't tell you you're doing a mistake. So:
"Vector<String> vs = ((Vector<String>) ((Object) new
Vector<Integer>));" would work. However, the next sequence would result
in a casting exceptions:
"vs.add(123); String s = vs.elementAt(0);", although generic wise it's
"supposed" to be safe (since vs is Vector<String>). To tell you this,
the compiler emits the warning you saw.
Robert Klemme - 01 Sep 2006 16:07 GMT
>>  > and how to avoid it w/o
>>> turning warnings off?
>> Don't do unnecessary casts up and down the class hierarchy.
>
> Wrong.

Why is that wrong?  Is not Object the super class of Vector and also
Vector<File> for that matter?

    robert
aaronfude@gmail.com - 01 Sep 2006 16:40 GMT
OK, my example was just the simplest thing I could think of. My real
problem is that I need to store Vector<String> in a collection with
other Objects. As a result, when I retrieve on Object via a get() I
need to cast it to a Vector<String> and the cast causes the warning. So
my casts are not unnecessary.
Zaph0d - 01 Sep 2006 19:12 GMT
robert:
> Why is that wrong?  Is not Object the super class of Vector and also
> Vector<File> for that matter?

This is wrong because the original warning did not refer to that
problem.

> OK, my example was just the simplest thing I could think of. My real
> problem is that I need to store Vector<String> in a collection with
> other Objects. As a result, when I retrieve on Object via a get() I
> need to cast it to a Vector<String> and the cast causes the warning. So
> my casts are not unnecessary.

Your cast are necessary, but you shouldn't cast to Vector<String> but
to Vector. If you cast to Vector<String> and it's not (if it's
Vector<Integer> for example), you'll get weird runtime errors in
unpredictable places.
Also, please be aware that you can't test for Vector<String> but just
for Vector (erasure again). Makes life a little more complicated.
aaronfude@gmail.com - 01 Sep 2006 20:02 GMT
You mean,
 Vector<String> v = (Vector) (Object) new Vector<String>();
?

Well, that causes another warning:

Type safety: The expression of type Vector needs unchecked conversion
to conform to
Vector<String>
Zaph0d - 02 Sep 2006 13:18 GMT
> You mean,
>   Vector<String> v = (Vector) (Object) new Vector<String>();
[quoted text clipped - 5 lines]
> to conform to
>  Vector<String>

Of course, becuase v is Vector<String> while the right-hand side is
typecasted to Vector.
This means that you expect v.get(...) to return String, but it might
throw a typecast exception (becuase the original isn't a String).
Robert Klemme - 02 Sep 2006 21:49 GMT
> robert:
>> Why is that wrong?  Is not Object the super class of Vector and also
>> Vector<File> for that matter?
>
> This is wrong because the original warning did not refer to that
> problem.

Ah, I see.  Thanks for the heads up!

    robert
aaronfude@gmail.com - 03 Sep 2006 12:48 GMT
So, to sum up, no way to get rid of the warning?
Zaph0d - 03 Sep 2006 18:14 GMT
> So, to sum up, no way to get rid of the warning?
huh? how did you come up with that?

Just do Vector<YourType> vec = new Vector<YourType>();
aaronfude@gmail.com - 03 Sep 2006 22:07 GMT
Happy to explain again. (Pseudo code...)

TreeMap<Object, Object> miscStuff = new TreeMap<Object, Object>();

miscStuff.put("A Vector of Ints", new Vector<Integer>());
miscStuff.put("A Vector of Strings", new Vector<String>());

Now:

Vector<Integer> v = (Vector<Integer>) miscStuff.get("A Vector of
Ints");
gives a warning

Vector<Integer> v = (Vector) miscStuff.get("A Vector of Ints");
gives a warning

Vector<Integer> v = miscStuff.get("A Vector of Ints");
gives an error

What is your suggestion?

Thank you
John W. Kennedy - 04 Sep 2006 02:29 GMT
> Happy to explain again. (Pseudo code...)
>
[quoted text clipped - 16 lines]
>
> What is your suggestion?

Redesign miscStuff so as not to be filled with different things.

Failing that, use the first option, and accept the warning.

Signature

John W. Kennedy
"The blind rulers of Logres
Nourished the land on a fallacy of rational virtue."
  -- Charles Williams.  "Taliessin through Logres: Prelude"

Zaph0d - 04 Sep 2006 07:39 GMT
> Failing that, use the first option, and accept the warning.
Failgin that, use Vector<Object> to bypass the warning (though gain no
real type-safety).
Hendrik Maryns - 04 Sep 2006 09:53 GMT
Zaph0d schreef:
>> Failing that, use the first option, and accept the warning.
> Failgin that, use Vector<Object> to bypass the warning (though gain no
> real type-safety).

Failing that, use @SuppressWarnings("unchecked")

H.
- --
Hendrik Maryns

==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
ricky.clarkson@gmail.com - 04 Sep 2006 11:08 GMT
Aaron,

A TreeMap<Object,Object> is intrinsically not a usefully typed
collection; you have just added it to make the compiler shut up, or
because you think you should for generics.

In your case, it appears that you are using Strings as keys, and either
a Vector<Integer> or a Vector<String> as a value.

The problem with this is that at runtime, Vector<Integer> is just a
Vector, and Vector<String> is just a Vector; there is no way for the
compiler or the runtime to ensure that you are operating on what you
think you are.  Throw an invisible ball to your friend; you cannot know
whether he caught it.

Polymorphism is a useful tool for dealing with this.  As you are using
Vector, your Java book probably predates modern code, so I'll
demonstrate this with abstract classes rather than interfaces.

This solution makes a homogenous (same-type) collection out of what was
a heterogenous (lots of different types) collection.  Another solution
might be to make more than one collection instead, one for each type.
Anyway, here goes the visitor design pattern:

abstract class VectorHolder
{
       public abstract void accept(VectorVisitor visitor);
}

abstract class VectorVisitor
{
       public abstract void visitStringVector(Vector<String> vector);
       public abstract void visitIntegerVector(Vector<Integer>
vector);
}

class StringVectorHolder extends VectorHolder
{
       private final Vector<String> vector;

       public StringVectorHolder(Vector<String> vector)
       {
               this.vector=vector;
       }

       public void accept(VectorVisitor visitor)
       {
               visitor.visitStringVector(vector);
       }
}

class IntegerVectorHolder extends VectorHolder
{
       private final Vector<Integer> vector;

       public IntegerVectorHolder(Vector<Integer> vector)
       {
               this.vector=vector;
       }

       public void accept(VectorVisitor visitor)
       {
               visitor.visitIntegerVector(vector);
       }
}

Now your map is:

TreeMap<String,VectorHolder>

If you have more types than just these two, you can add a method in
VectorVisitor, e.g., visitColor, and then make a ColorVectorHolder.  Of
course, VectorHolder and VectorVisitor might be bad names if you use
anything other than Vectors there..

Don't dismiss this immediately as being a lot of useless code; it is
giving you real runtime information about the elements in your
collection, without you having to cast.

Casting is for magicians.

> Happy to explain again. (Pseudo code...)
>
[quoted text clipped - 18 lines]
>
> Thank you
ricky.clarkson@gmail.com - 04 Sep 2006 11:16 GMT
And now the same thing in my preferred coding style:

interface Holder
{
       void accept(Visitor visitor);
}

interface Visitor
{
       void visitStringList(List<String> list);
       void visitIntegerList(List<Integer> list);
}

class Holders
{
       public static Holder stringList(final List<String> list)
       {
               return new Holder()
               {
                       public void accept(Visitor visitor)
                       {
                               visitor.visitStringList(list);
                       }
               };
       }

       public static Holder integerList(final List<Integer> list)
       {
               return new Holder()
               {
                       public void accept(Visitor visitor)
                       {
                               visitor.visitIntegerList(list);
                       }
               };
       }
}

TreeMap<String,Holder> map=new TreeMap<String,Holder>();

map.put("a list of ints",Holders.integerList(new
ArrayList<Integer>()));

map.put("a list of strings",Holders.stringList(new
ArrayList<String>()));

No type safety lost, and generics as erasure is causing no problems, as
usual.

> Aaron,
>
[quoted text clipped - 99 lines]
> >
> > Thank you
Greg R. Broderick - 04 Sep 2006 18:38 GMT
aaronfude@gmail.com wrote in news:1157284132.474909.299540
@m79g2000cwm.googlegroups.com:

> So, to sum up, no way to get rid of the warning?

Not if you want to continue storing the Vector of Strings in a collection
with other Objects -- your design is intentionally defeating Java's type
safety rules.

Cheers!
GRB

Signature

---------------------------------------------------------------------
Greg R. Broderick            gregb.usenet200607@blackholio.dyndns.org

A. Top posters.
Q. What is the most annoying thing on Usenet?
---------------------------------------------------------------------

aaronfude@gmail.com - 07 Sep 2006 15:57 GMT
> aaronfude@gmail.com wrote in news:1157284132.474909.299540
> @m79g2000cwm.googlegroups.com:
[quoted text clipped - 7 lines]
> Cheers!
> GRB

Point well taken, but how do I clone() a Vector<Integer> without a
warning?
Hendrik Maryns - 07 Sep 2006 16:25 GMT
aaronfude@gmail.com schreef:
>> aaronfude@gmail.com wrote in news:1157284132.474909.299540
>> @m79g2000cwm.googlegroups.com:
[quoted text clipped - 9 lines]
> Point well taken, but how do I clone() a Vector<Integer> without a
> warning?

new Vector<Integer>(oldVector);

Are you sure you do not want an ArrayList?

H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
ricky.clarkson@gmail.com - 10 Sep 2006 17:25 GMT
Clone is a broken API in the context of Java 1.5, because it actually
mentions Object.

Object was only necessary without generics, now we can use type
parameters.

Angelika Langer has something to say on the matter:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#How
%20do%20I%20best%20implement%20the%20clone%20method%20of%20a%20parameterized%20t
ype


Cloning is very often not what you want anyway, as it is shallow
copying.

Serialising and deserialising tends to be more thorough, but very
wasteful.  I'd rather avoid 'magic' behaviour, and write an explicit
copy constructor or factory method, which is the approach the Java
collections APIs take.

Cheers.

> > aaronfude@gmail.com wrote in news:1157284132.474909.299540
> > @m79g2000cwm.googlegroups.com:
[quoted text clipped - 10 lines]
> Point well taken, but how do I clone() a Vector<Integer> without a
> warning?
M.J. Dance - 01 Sep 2006 15:01 GMT
> Why does the following code cause a warning and how to avoid it w/o
> turning warnings off?
>
> Vector<File> a = (Vector<File>) (Object) new Vector<File>();

Vector<File> a = new Vector<File>();


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.