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 / GUI / March 2005

Tip: Looking for answers? Try searching our database.

Why Image can be cast inot a BufferedImage?

Thread view: 
hiwa - 11 Mar 2005 11:23 GMT
A newbie student wrote the code:

/* in a custom Component class */
BufferedImage bi = (BufferedImage)createImage(100, 100);

I gave him a cruelly low grade.

But, alas, compiler silently bless it.

What the rationale could we find in the JLS for the above?

Also, save me from:

//in a typical paint method
Graphics2D g2 = (Graphics2D)g;
Andrey Kuznetsov - 11 Mar 2005 11:35 GMT
> /* 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

Thomas Weidenfeller - 11 Mar 2005 12:31 GMT
> 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    *



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.