> /* in a custom Component class */
> BufferedImage bi = (BufferedImage)createImage(100, 100);
[quoted text clipped - 9 lines]
> //in a typical paint method
> Graphics2D g2 = (Graphics2D)g;
Graphics Object from paint method _is_ Graphics2D Object
but createImage returns Image and not BufferedImage.
for compiler both casts are legal, but at runtime you will get
ClassCastException with first one.

Signature
Andrey Kuznetsov
http://uio.dev.java.net Unified I/O for Java
http://reader.imagero.com Java image reader
http://jgui.imagero.com Java GUI components and utilities
> A newbie student wrote the code:
>
> /* in a custom Component class */
> BufferedImage bi = (BufferedImage)createImage(100, 100);
>
> I gave him a cruelly low grade.
IMHO the low grade is not justified at all. Sun says in:
http://java.sun.com/j2se/1.5.0/docs/guide/2d/spec/j2d-image.html#wp66509
Quote:
To create a BufferedImage, call the Component.createImage
method; this returns a BufferedImage whose drawing
characteristics match those of the component used to
create it
Also, see the example in
http://java.sun.com/docs/books/tutorial/2d/images/doublebuffering.html
> But, alas, compiler silently bless it.
It has to. It is a cast. It could blow up during runtime, but apparently
it shouldn't, since Sun says this is the way to do it.
> What the rationale could we find in the JLS for the above?
The JLS doesn't specify the APIs, just the core language. I remember to
even see this mentioned in some older (pre 1.5) API documentation, but I
can't find it at the moment. Maybe I am getting old, and it was never there.
But anyhow, one can find some find justifications in at least the two
sources which I provided above. So I would let your student off the hock
- pronto :-)
> Also, save me from:
>
> //in a typical paint method
> Graphics2D g2 = (Graphics2D)g;
This is also correct and sanctioned by Sun. E.g.
http://java.sun.com/j2se/1.5.0/docs/guide/2d/spec/j2d-intro.html#wp63962
One could skip the additional object reference and cast all usages of g
in the paint method to Graphics2D, but the above shown cast and
assignment is common and simplifies the later code.
/Thomas

Signature
The comp.lang.java.gui FAQ:
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
hiwa - 12 Mar 2005 20:22 GMT
> > A newbie student wrote the code:
> >
[quoted text clipped - 47 lines]
>
> /Thomas
Thanks Thomas.
But implication of my question is rather theoretical than whatever actual/factual.
[Essence of the question]
Return type of createImage() is Image.
Type of argument g is Graphics.
Java prohibits casting superclass object into its subclass type.
(It is illegal in assignment conversion -- JLS 5.2, 5.5.)
(1)Then, why they are silently allowed? :
BufferedImage bi = (BufferedImage)createImage(100, 100);
Graphics2D g2 = (Graphics2D)g;
Those type information should be static. Not runtime resolution.
They are part of API contract.
(2)Then, why these errors(?) can't be statically checked?
Mark Thornton - 12 Mar 2005 21:28 GMT
>>>A newbie student wrote the code:
>>>
[quoted text clipped - 56 lines]
> Java prohibits casting superclass object into its subclass type.
> (It is illegal in assignment conversion -- JLS 5.2, 5.5.)
Java does not prohibit such casts, it just won't do them automatically.
> (1)Then, why they are silently allowed? :
> BufferedImage bi = (BufferedImage)createImage(100, 100);
[quoted text clipped - 3 lines]
> They are part of API contract.
> (2)Then, why these errors(?) can't be statically checked?
Ideally the return type of createImage would be changed to
BufferedImage, since Sun currently say that is what we can expect.
However there are compatibility problems in doing so --- existing
compiled code would fail unless you left in a method with the original
signature (at the JVM level, return type IS part of the signature).
Similarly it would be nice if the argument of paint was changed to
Graphics2D, but again this is probably more trouble than it is worth.
Mark Thornton
Ian Shef - 14 Mar 2005 20:31 GMT
<snip>
> [Essence of the question]
> Return type of createImage() is Image.
> Type of argument g is Graphics.
> Java prohibits casting superclass object into its subclass type.
> (It is illegal in assignment conversion -- JLS 5.2, 5.5.)
Yes, but a subclass object can be passed where the parameter is specified
as the superclass.
> (1)Then, why they are silently allowed? :
> BufferedImage bi = (BufferedImage)createImage(100, 100);
> Graphics2D g2 = (Graphics2D)g;
Graphics2D is a subclass of Graphics. The object passed in to
paint(Graphics g) is in reality a Graphics2D (or some further hidden
subclass?). Thus, it is legitimate to cast g to a Graphics2D.
I think that the Image/BufferedImage situation is similar. I suspect that
createImage actually returns a BufferedImage (a subclass of Image). I have
not read the source code to verify this, but it would explain what you see.
> Those type information should be static. Not runtime resolution.
> They are part of API contract.
> (2)Then, why these errors(?) can't be statically checked?
They aren't errors.
[Getting on soapbox]
What I think is an error, or at least a lack, is the lack of documentation.
Unless you find an example from Sun, there is nothing in the Java docs that
tells you that paint(Graphics g) is really going to receive a Graphics2D.
I realize that there are some subtleties here about what constitutes a
contract and what doesn't. I also realize that there are subtleties about
definition versus implementation. I further realize that, in the future,
Sun could change paint to actually provide (say) a Graphics4D which would
be a subclass of Graphics2D which is a subclass of Graphics. However, the
fact of the matter is that programmers who use these techniques are
entitled to real documentation and explanations, and should not have to
depend upon examples.
[Getting down from soapbox]
To be fair, the Graphics/Graphics2D part of this is documented at
http://java.sun.com/j2se/1.5.0/docs/guide/2d/spec/j2d-intro.html#wp63962
as noted by a previous writer.
But why isn't it in the Java docs?

Signature
Ian Shef 805/F6 * These are my personal opinions
Raytheon Company * and not those of my employer.
PO Box 11337 *
Tucson, AZ 85734-1337 *