Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Annoying 1.5 warnings

6 views
Skip to first unread message

aaro...@gmail.com

unread,
Sep 1, 2006, 9:54:30 AM9/1/06
to
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

unread,
Sep 1, 2006, 10:00:24 AM9/1/06
to
On 01.09.2006 15:54, aaro...@gmail.com wrote:
> 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

M.J. Dance

unread,
Sep 1, 2006, 10:01:06 AM9/1/06
to
aaro...@gmail.com wrote:
> 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>();

Zaph0d

unread,
Sep 1, 2006, 11:05:17 AM9/1/06
to
> > 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

unread,
Sep 1, 2006, 11:07:16 AM9/1/06
to
On 01.09.2006 17:05, Zaph0d wrote:
>> > 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

aaro...@gmail.com

unread,
Sep 1, 2006, 11:40:20 AM9/1/06
to
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

unread,
Sep 1, 2006, 2:12:33 PM9/1/06
to
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.

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.

aaro...@gmail.com

unread,
Sep 1, 2006, 3:02:35 PM9/1/06
to
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

unread,
Sep 2, 2006, 8:18:33 AM9/2/06
to

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

unread,
Sep 2, 2006, 4:49:09 PM9/2/06
to
Zaph0d wrote:
> 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

aaro...@gmail.com

unread,
Sep 3, 2006, 7:48:52 AM9/3/06
to
So, to sum up, no way to get rid of the warning?

Zaph0d

unread,
Sep 3, 2006, 1:14:27 PM9/3/06
to
> 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>();

aaro...@gmail.com

unread,
Sep 3, 2006, 5:07:08 PM9/3/06
to
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

unread,
Sep 3, 2006, 9:29:20 PM9/3/06
to

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

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

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

Zaph0d

unread,
Sep 4, 2006, 2:39:20 AM9/4/06
to
> 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

unread,
Sep 4, 2006, 4:53:38 AM9/4/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFE++mSe+7xMGD3itQRAkkfAKCAaQUPIHshnvhlcxZI7i+YRLTZXACaA//2
GFIoyXlEyBaqoJGcu1HT8L0=
=w4Q6
-----END PGP SIGNATURE-----

ricky.c...@gmail.com

unread,
Sep 4, 2006, 6:08:24 AM9/4/06
to
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.

ricky.c...@gmail.com

unread,
Sep 4, 2006, 6:16:04 AM9/4/06
to
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.

Greg R. Broderick

unread,
Sep 4, 2006, 1:38:51 PM9/4/06
to
aaro...@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


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

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

aaro...@gmail.com

unread,
Sep 7, 2006, 10:57:52 AM9/7/06
to

Greg R. Broderick wrote:
> aaro...@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
>
>

Point well taken, but how do I clone() a Vector<Integer> without a
warning?

Hendrik Maryns

unread,
Sep 7, 2006, 11:25:46 AM9/7/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

aaro...@gmail.com schreef:

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFFADn6e+7xMGD3itQRAqU3AJ92LSeha8Bxa5BAJCy55tmBNGWYwQCcDoae
YI0p/IjLSjHnUAOlX1uYAHw=
=9RoR
-----END PGP SIGNATURE-----

ricky.c...@gmail.com

unread,
Sep 10, 2006, 12:25:10 PM9/10/06
to
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%20type

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.

0 new messages