Annoying 1.5 warnings

A

aaronfude

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
 
R

Robert Klemme

Why does the following code cause a warning

Because you cast from Object to Vector said:
> 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

M.J. Dance

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>();
 
Z

Zaph0d

and how to avoid it w/o
Don't do unnecessary casts up and down the class hierarchy.

Wrong.

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.
 
A

aaronfude

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.
 
Z

Zaph0d

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.
 
A

aaronfude

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>
 
Z

Zaph0d

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>

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).
 
Z

Zaph0d

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>();
 
A

aaronfude

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
 
J

John W. Kennedy

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?

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

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

Zaph0d

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).
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Zaph0d schreef:
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-----
 
R

ricky.clarkson

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.
 
R

ricky.clarkson

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.
 
G

Greg R. Broderick

(e-mail address removed) wrote in @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 (e-mail address removed)

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

aaronfude

Greg said:
(e-mail address removed) wrote in @m79g2000cwm.googlegroups.com:


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?
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top