Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > type safety in java 1.5 (bug or hole?)

Reply
Thread Tools

type safety in java 1.5 (bug or hole?)

 
 
York Werres
Guest
Posts: n/a
 
      05-17-2004
Hi,

Gilad Bracha writes in chapter 7.3 of "Generics in the Java Programming
Language" this:

In particular, the language is designed to guarantee
that if your entire application has been compiled
without unchecked warnings using javac -source 1.5,
it is type safe.

But, believe it or not, my *very first* experiment at all with Java 1.5 was
this:

List<? super Number> list = new ArrayList<Serializable>();
list.add(new Double(0.0));
Integer theInt = (Integer) list.get(0);

I compiled it with "-source 1.5" (JDK 1.5.0 beta 1) and there were no
warnings at all. I then ran it and got a ClassCastException (as expected).

Why exactly is this called "type safe"?

Or to put the question another way: This is a bug, right?

My explanation attempt: The "? super Number" is a contra-variant bounded
wildcard which should be write-only. The compiler should not allow me to do
the "list.get(0)". The cast to Integer is ok, but calling the get is not
(because of it's return type).

Is this a known bug or do I have to report it somewhere?

BTW: This really is my very first experiment with Java generics and it
doesn't make me happy at all. What good are generics if they're not type
safe?

2004-05-17, York.
--
werres at uni minus bremen.de
http://www.uni-bremen.de/~werres


 
Reply With Quote
 
 
 
 
Chris Smith
Guest
Posts: n/a
 
      05-17-2004
York Werres wrote:
> Gilad Bracha writes in chapter 7.3 of "Generics in the Java Programming
> Language" this:
>
> In particular, the language is designed to guarantee
> that if your entire application has been compiled
> without unchecked warnings using javac -source 1.5,
> it is type safe.


Right... but not if you explicitly do type-unsafe things. That sentence
is probably just fine if taken in context, but when you cast a reference
to something incompatible with the class of object it refers to, the
only thing that *can* happen is a ClassCastException!

> But, believe it or not, my *very first* experiment at all with Java 1.5 was
> this:
>
> List<? super Number> list = new ArrayList<Serializable>();
> list.add(new Double(0.0));
> Integer theInt = (Integer) list.get(0);


The cast is the problem. Because there's no upper bound on the type of
the return value from List.get, the return type is effectively Object.
You could have said:

Object theNum = list.get(0);

And that would have been fine. But if you make your own further
assumptions after getting a number out of the list, and even add a cast
to insist to the compiler that it ignore your type-unsafe programming,
then you're no longer type-safe.

> My explanation attempt: The "? super Number" is a contra-variant bounded
> wildcard which should be write-only. The compiler should not allow me to do
> the "list.get(0)".


The method is guaranteed to return a value, and since all objects in
Java are subclasses of Object, that value is guaranteed to be either
null or a reference to an Object. Hence, it can return a value of type
Object. There's no reason for the compiler to prohibit this call.

> The cast to Integer is ok, but calling the get is not
> (because of it's return type).


When you cast something, you're informing the compiler that even though
it can't prove that the value references an instance of the desired
class, *you* know that it does and the compiler should trust you.
You're essentially lying to the compiler; that reference doesn't point
to an Integer, even though you promised that it does.

Note that this has nothing to do with generics. You have a variable of
type Object, which refers to an object of class Double, and you're
trying to cast the reference to type Integer. That will always yield a
ClassCastException. The fact that you obtained the Object-typed
reference from a generic collection is irrelevant. It's your cast that
causes the ClassCastException.

> BTW: This really is my very first experiment with Java generics and it
> doesn't make me happy at all. What good are generics if they're not type
> safe?


They are type-safe. However, if you write your own non-generic code
with arbitrary casting to other classes, then your non-generic code
obviously won't be type-safe. If you want type-safety, then don't cast.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
Reply With Quote
 
 
 
 
John C. Bollinger
Guest
Posts: n/a
 
      05-17-2004
York Werres wrote:

> Hi,
>
> Gilad Bracha writes in chapter 7.3 of "Generics in the Java Programming
> Language" this:
>
> In particular, the language is designed to guarantee
> that if your entire application has been compiled
> without unchecked warnings using javac -source 1.5,
> it is type safe.
>
> But, believe it or not, my *very first* experiment at all with Java 1.5 was
> this:
>
> List<? super Number> list = new ArrayList<Serializable>();
> list.add(new Double(0.0));
> Integer theInt = (Integer) list.get(0);
>
> I compiled it with "-source 1.5" (JDK 1.5.0 beta 1) and there were no
> warnings at all. I then ran it and got a ClassCastException (as expected).
>
> Why exactly is this called "type safe"?
>
> Or to put the question another way: This is a bug, right?


If "type safe" is supposed to mean "will never generate a
ClassCastException", and if Bracha's comments are an accurate expression
of part of the intent of generics, then I'd say yes, it's a bug.

> My explanation attempt: The "? super Number" is a contra-variant bounded
> wildcard which should be write-only. The compiler should not allow me to do
> the "list.get(0)". The cast to Integer is ok, but calling the get is not
> (because of it's return type).


No, I don't buy that. The compiler knows that all objects are instances
of Object, so it can safely assume that the return value of list.get(0)
is an Object, and it can therefore allow the call without a warning.
The declared type parameter for the specific list reference does not
allow a more specific assumption to be made, however, so the cast to
Integer should generate an unchecked warning.

> Is this a known bug or do I have to report it somewhere?


I didn't see it in the bug database, but it seems like a pretty basic
situation, so I'm a bit surprised. The place to which you would report
such a bug is

http://developer.java.sun.com/develo...e/index.jshtml

You need membership (free) in the Sun Developer Network to read the list
or post new bugs.

> BTW: This really is my very first experiment with Java generics and it
> doesn't make me happy at all. What good are generics if they're not type
> safe?


Little good, I'd say, but
(1) They are intended to be type safe, and will be to the greatest
extent possible before Java 1.5 emerges from testing
(2) I think the use of generics in the example code obscures the fact
that the unsafe operation doesn't really involve generics at all --
rather, it involves a cast of a reference of type Object to a more
specific type (the former type is the result of the evaluation of a
genericly-typed expression, but the generics are out of the picture by
the time the cast comes around)
(3) Generics do provide a very handy syntax for some common things, and
even if they have type safety bugs, they aren't any worse than the
equivalent problems in non-generic code.


John Bollinger
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Michael Borgwardt
Guest
Posts: n/a
 
      05-17-2004
York Werres wrote:
> Or to put the question another way: This is a bug, right?


No.

> My explanation attempt: The "? super Number" is a contra-variant bounded
> wildcard which should be write-only.


I really have no ideal what you mean with "write-only" in this context.
I have no experience with using generics, but the way I understand it is
that it ensures that the variable is only allowed to contain generic Lists
whose contents are Number or one of its superclasses. The result is that
the compiler will protest if you call put() on the variable with something
that cannot be put into the List object the variable refers to.

> The compiler should not allow me to do
> the "list.get(0)".


why not?

> The cast to Integer is ok,


No, the cast to Integer is exactly what is NOT OK about your code.

 
Reply With Quote
 
Phillip Lord
Guest
Posts: n/a
 
      05-17-2004
>>>>> "York" == York Werres <(E-Mail Removed)> writes:

York> Hi,

York> Gilad Bracha writes in chapter 7.3 of "Generics in the Java
York> Programming Language" this:

York> In particular, the language is designed to guarantee that if
York> your entire application has been compiled without unchecked
York> warnings using javac -source 1.5, it is type safe.

York> But, believe it or not, my *very first* experiment at all with
York> Java 1.5 was this:

York> List<? super Number> list = new ArrayList<Serializable>();
York> list.add(new Double(0.0)); Integer theInt = (Integer)
York> list.get(0);


Not over casts. The system has broken because you have explicitly told
it about this cast, claimed that it is safe and you wrong.

I'm a little surprised that it doesn't give you can't turn a warning
on, to tell you when a cast is being used though.

York> I compiled it with "-source 1.5" (JDK 1.5.0 beta 1) and there
York> were no warnings at all. I then ran it and got a
York> ClassCastException (as expected).

York> Why exactly is this called "type safe"?

York> Or to put the question another way: This is a bug, right?


I'm deeply unconvinced that this is a bug. The problem is that you are
reading a tutorial. By chapter 7.3 I suspect the author had assumed
that you are no longer inserting casts. I'd suggest that you read the
specification instead, which will tell you of the expected behaviour
when hitting a cast.



York> BTW: This really is my very first experiment with Java
York> generics and it doesn't make me happy at all. What good are
York> generics if they're not type safe?


Clearly java 1.5 has to support non type safe code, if it is to be
backward compatible. The question is whether the features allow to
leave out the cast and still program usefully. If you remove the cast
from 1.4, say, then writing any sort of code base would become nearly
impossible. The hope is that with generics this will no longer be
true.

Phil
 
Reply With Quote
 
Chris Uppal
Guest
Posts: n/a
 
      05-17-2004
York Werres wrote:

> List<? super Number> list = new ArrayList<Serializable>();


I'm not sure what you are trying to do here. Where does <Serializable> come
from ? Also, were you trying to make the declared type of list be a List of
Number ? I.e. a List that can (statically) be known to contain only instances
of Number and its subclasses ? If so then I think it should be declared:

List<Number> list = ...;

To be honest, I have no idea what the use of a wildcard in declaring a variable
is supposed to mean. The same goes for the use of a bound on the type (if I've
got the terminology right). I had thought they were only used in defining
generic classes and methods.


> list.add(new Double(0.0));


OK, so now you have successfully added a Double to the list.


> Integer theInt = (Integer) list.get(0);


If you had declared list to be a List<Number> then the static type of
list.get(0);
would be Number, and so the compiler would accept (statically) the cast from
Number to Integer. It would also require that cast. You've actually declared
it to be a wildcard which I'm assuming was a mistake. However, the /actual/
object returned by the expression is a Double, and Double is not assignable to
Integer and so the runtime cast must fail, exactly as if you'd written:

Number theNumber = new Double(0.0);
Integer theInteger = (Integer) theNumber;

or, even:

Object theObject = new Double(0.0);
Integer theInteger = (Integer) theObject;

which pass the compile-time type checks, but obviously must fail at runtime.

-- chris


 
Reply With Quote
 
York Werres
Guest
Posts: n/a
 
      05-17-2004
"Chris Smith" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed)4.net...

> > What good are generics if they're not type safe?

>
> They are type-safe. However, if you write your own non-generic code
> with arbitrary casting to other classes, then your non-generic code
> obviously won't be type-safe. If you want type-safety, then don't cast.


Yeah, I got that myself just a minute after posting (sorry): What had
mislead me for the moment (it was my first experiment with a Java 1.5
feature, after all) were Bracha's explicit and even highlighted words "the
language is designed to guarantee that if your entire application has been
compiled without unchecked warnings using javac -source 1.5, it is type
safe". There was absolutely no context that restricted this statement in the
paper to code completely without casts!

What I concluded (again: sorry that this was just *after* posting) was that
for making old code type safe, it is more important to first get rid of the
casts than to get rid of the compiler warnings. If the warnings are gone and
the casts are still there, you might still have the exceptions. But if the
casts are gone, so is most of the exception risk -- even if there are still
warnings:

List list1 = new ArrayList();
list1.add(new Double(0.0)); // <-- unsafe code (compiler issues warning)
Integer n1 = (Integer) list1.get(0); // <-- exception at runtime

List<? super Number> list2 = new ArrayList<Serializable>();
list2.add(new Double(0.0)); // <-- now safe code (no more warning)
Integer n2 = (Integer) list2.get(0); // <-- still exception at runtime

List<Integer> list3 = new ArrayList(); // <-- unsafe code (still a
warning)
list3.add(new Integer(0));
Integer n3 = list3.get(0); // <-- no more cast, no more exception

I had expected that the compiler warnings are there to guide the developer
towards type safety. And the explicit statement in Bracha's paper stongly
encouraged me to believe that.

The least I would have expected would be a compiler warning if the compiler
can infer that a cast is not type safe. Why are there no warnings for unsafe
casts? Is there a reason? After all, as seen above, it's the casts that must
be eliminated first. So there should be a compiler's help to *find* them.
This would also render the type safety statement in Bracha's paper true.

(Besides: I can tell my employer that, for the benefit of his/her company, I
have to get rid of the evil warnings. But I can not tell her that I have to
get rid of all the casts first -- just because I want to. She won't
unterstand why the greater threat to type safety, the casts, don't cause
warnings. They can't be that evil then, can't they?)

2004-05-17, York.
--
werres at uni minus bremen.de
http://www.uni-bremen.de/~werres


 
Reply With Quote
 
Chris Smith
Guest
Posts: n/a
 
      05-17-2004
Phillip Lord wrote:
> I'm deeply unconvinced that this is a bug. The problem is that you are
> reading a tutorial. By chapter 7.3 I suspect the author had assumed
> that you are no longer inserting casts. I'd suggest that you read the
> specification instead, which will tell you of the expected behaviour
> when hitting a cast.


I thought so, too... but the only specification I can find (for the JSR-
14 public review) is from 2001, and doesn't mention these wildcards as
far as I can see. Is there a better place to look?

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      05-17-2004
On Mon, 17 May 2004 14:36:49 +0200, "York Werres"
<(E-Mail Removed)> wrote or quoted :

> List<? super Number> list = new ArrayList<Serializable>();


I think it only works if you make the left and right side of that
identical. The compiler can't track what kind of collection you have
pointed to by a reference only the type of the reference. All it can
check is for line by line legality.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
 
Reply With Quote
 
Scott Ellsworth
Guest
Posts: n/a
 
      05-17-2004
In article <(E-Mail Removed)>,
"York Werres" <(E-Mail Removed)> wrote:

> (Besides: I can tell my employer that, for the benefit of his/her company, I
> have to get rid of the evil warnings. But I can not tell her that I have to
> get rid of all the casts first -- just because I want to. She won't
> unterstand why the greater threat to type safety, the casts, don't cause
> warnings. They can't be that evil then, can't they?)


I suspect that Eclipse and IDEA will have warnings for casts of typed
collections by the time 1.5 ships, if not before. See if you can grab
one of these tools, as then you will get warning messages sufficient to
convince your employer to let you fix them.

If nothing else, if your current code works, then it will not hurt it to
put in a type safe collection, which you can then do a Find Usages on to
walk down the tree.

Scott
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Combining Java Reflection API with Java Annotation Types for Thread Safety pek Java 2 10-23-2007 03:00 PM
Enumerators, Templates, and Type Safety Matt Taylor C++ 6 07-13-2004 01:16 PM
newbie question on "Type Safety" Raymond Du ASP .Net 1 06-21-2004 11:42 AM
program surgery vs. type safety Aaron Watters Python 12 11-17-2003 03:17 PM
Runtime type-safety (for linked lists) Dave C Programming 2 09-29-2003 09:42 AM



Advertisments