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 / General / January 2008

Tip: Looking for answers? Try searching our database.

Type conversion for reference types?

Thread view: 
Peter Duniho - 09 Jan 2008 06:07 GMT
My apologies if this is a silly question in the context of Java.  I'm very  
new to the language, though I've got lots of experience in others  
(including C#, which has borrowed a lot from Java) and programming  
generally.

I am wondering what facility for type conversion of reference types, if  
any, exists in Java.  And more specifically, if none exists, how do I  
reliably deal with situations where I want a specific sub-class but am  
only given some base class.  I mean, is there anything unique to Java that  
provides for this, or is it really just as simple as "casting only works  
if the actual instance type is compatible with the destination type" (for  
example, in C# you can write explicit type conversions that allow  
arbitrary code to execute to convert from one type to another).

The two particular examples are Graphics and Graphics2D, and Rectangle2D  
and Rectangle2D.Double.

With respect to Graphics/Graphics2D, I've seen lots of examples of AWT  
code where in a paint() method, the Graphics instance passed in is cast to  
Graphics2D.  I've done this myself in my own code and it appears to work  
fine.  But:

    * How can I be guaranteed that the cast will succeed?
    * Is there a type conversion that will ensure it always will?
    * Or will the code fail if it's run in an environment where a plain  
Graphics instance is passed?

The second example comes up in the context of using an Area object.  I  
want to be able to get the bounding rectangle from the Area object and use  
the exact location and size of the rectangle to do some geometric  
contraining code.  But Area.getBounds() returns a Rectangle2D, which  
doesn't expose the fields that provide that information (they're in the  
sub-classes).

The Rectangle class (base class for Rectangle2D) does have "get" methods  
for these values (getX(), getY(), getWidth(), getHeight()) and I can use  
those.  But for grins I tried casting the Rectangle2D to a  
Rectangle2D.Double and it worked fine.  Again, I'm curious of pretty much  
the same questions I have for the Graphics class.  Is this something I can  
either count on, or force to always happen?  Or did I just luck out?

Thanks,
Pete
Stefan Ram - 09 Jan 2008 06:25 GMT
>I am wondering what facility for type conversion of reference
>types, if  any, exists in Java.

 The type of an expression can be set by a cast.

>And more specifically, if none exists, how do I  reliably deal
>with situations where I want a specific sub-class but am  only
>given some base class.

 This is done by a downcast and treated in most textbooks.

 For example, »Casting Objects« in

http://java.sun.com/docs/books/tutorial/java/IandI/subclasses.html

>provides for this, or is it really just as simple as "casting only works  
>if the actual instance type is compatible with the destination type"

 In the expression »(type)reference«, where »type« is a type
 name and »reference« is a reference expression, the reference
 must evaluate to null or the type of the object refered to
 must be a subtype of the type »type«. (1)

>* How can I be guaranteed that the cast will succeed?

 An upcast always succeeds, once the program was compiled.
 The corresponding type conversion can also be done
 implicitly, without a cast operator.

 For a downcast, you need to make sure that (1) holds.
 This is being tested at runtime and will throw
 an exception otherwise.
Stefan Ram - 09 Jan 2008 06:53 GMT
>This is done by a downcast and treated in most textbooks.

 I would like to elaborate:

 Types of expressions are known at compile time, while
 types of objects are known only at run time in the general case.

 Let r be a reference-valued expression (syntactically, a
 »UnaryExpressionNotPlusMinus«).

 Let T be a reference type (syntactically, a »ReferenceType«).

 Then

     (T)r

 is an expression, called a »cast expression« (»CastExpression«).

 If the value of »r« is null, then the value of the cast
 expression is the null reference cast to T.

 Otherwise, the value of the expression r refers to an object.

 Let O be the type of this object. (O is a class.)
 Let R be the type of r.

 A type »T« here is called a »supertype« of a type »S«
 iff T is equal to S or
 iff »S« directly or indirectly extends or implements T.

 A reference expression can only be used to evaluate
 to a reference value that refers an object if the type
 of the reference expression is a supertype of the
 type of the object.

 Therefore, we require that in »(T)r«, T is a supertype of O
 (the object refered to by the value of »r«).

 If T is a supertype of R, this holds. Such a cast is called
 an »upcast«.

 If R is a supertype of T and not equal to T, then whether T
 is a supertype of O in the general case can only be known
 at runtime, because the type of O is only known at run time,
 except that it is already known that it must be a subtype
 of R. Such a cast is called a »downcast«.
Knute Johnson - 09 Jan 2008 06:31 GMT
> My apologies if this is a silly question in the context of Java.  I'm
> very new to the language, though I've got lots of experience in others
[quoted text clipped - 40 lines]
> Thanks,
> Pete

If it isn't it won't is the rule.  And there are a lot hidden in there
like the Graphics and Graphics2D.

Signature

Knute Johnson
email s/nospam/knute/

Lew - 09 Jan 2008 06:32 GMT
> I am wondering what facility for type conversion of reference types, if
> any, exists in Java.  And more specifically, if none exists, how do I
> reliably deal with situations where I want a specific sub-class but am
> only given some base class.  I mean, is there anything unique to Java
> that provides for this, or is it really just as simple as "casting only
> works if the actual instance type is compatible with the destination type"

Downcasts are legal, upcasts are unnecessary.

You can always cast from a base type, e.g., Number, down to the actual type of
the object at run-time, or anything in between:

   Number someNumber = getItSomehow();
   Long lval = (Long) someNumber;

Of course, if someNumber is actually a Double, you'll raise a ClassCastException.

Upcasting is a "widening conversion" and doesn't require explicit syntax:

Number num = Long.valueOf( 1L );

> (for example, in C# you can write explicit type conversions that
> allow arbitrary code to execute to convert from one type to another).

Not so, Java.  You can in some situations write a constructor or factory
method that generates an equivalent instance in a different class:

   Number num = Long.valueOf( "1" );

You need to call this method everywhere it matters.

  String momsAge = request.getParameter( "momsAge" );
  Person mom = new Mom();
  mom.setAge( Long.valueOf( momsAge ));

You never know.  Cryogenics, advances in stem cells, genetics, they'll cure
all viral diseases - better to give enough range.

> With respect to Graphics/Graphics2D, I've seen lots of examples of AWT
> code where in a paint() method, the Graphics instance passed in is cast
> to Graphics2D.  I've done this myself in my own code and it appears to
> work fine.  But:
>
>     * How can I be guaranteed that the cast will succeed?

Someone up in Valhalla said, "Trust us!"

Don't worry, if they ever change it then your program will blow up with a
ClassCastException, so you'll know.

>     * Is there a type conversion that will ensure it always will?

It's called, "The actual object always (coincidentally) happens to be a
Graphics2D."  In other words, no.  But you're talking about the Swing API,
which happens to use only Graphics2D objects, so you're good.

Here's one for people who complain about Java's type safety.  You are asking
for more type safety - a more restrictive type in the method signature.  As
well you should - it is very much a hack that type safety is circumvented
here.  I believe it has to do with needing to override AWT methods, which do
not guarantee to have Graphics2D arguments, and thus not being able to change
the signature.  So the Swing hack is not to promise you anything, but give you
(nudge, nudge, wink, wink) a Graphics2D on the sly.

>     * Or will the code fail if it's run in an environment where a plain
> Graphics instance is passed?

These are Swing methods.  Swing methods will do what they're documented to do.
 Cast away with impunity.

You could, I suppose, write a custom component that somehow subverts the
promise.  Don't do that.

I leave the other questions to those more expert than I.

Signature

Lew

Peter Duniho - 09 Jan 2008 08:57 GMT
Okay, so bottom line: no implicit type conversions (that is, something  
that actually modifies the data) for reference types.  Only straight  
casting.

Thanks for the explanation, even if it does still leave me with the  
uncomfortable question of "how do I know what I'm really getting?"

And one other thing you mentioned:

> [...]
>>     * Is there a type conversion that will ensure it always will?
>
> It's called, "The actual object always (coincidentally) happens to be a  
> Graphics2D."  In other words, no.  But you're talking about the Swing  
> API, which happens to use only Graphics2D objects, so you're good.

Am I talking about the Swing API?

I made a specific choice to try to avoid Swing.  The program I'm writing  
isn't going to use any advanced controls anyway, and I'd prefer that what  
controls I do use be using native controls on each platform, to retain  
native look-and-feel.

(As an aside, the three main APIs I looked at were AWT, Swing, and SWT.  
SWT has so far produces far superior graphical rendering for me, but I'm  
put off by the need to deliver a separate library for each platform I want  
to support.  With AWT and Swing, if a recent enough Java is installed, the  
same Java program should run on any platform, as I understand it.  From  
what I've read, Swing reimplements all of the controls and always will  
look the same regardless of the host OS).

Graphics and Graphics2D are both in java.awt, and I just assumed that  
Graphics2D was actually part of AWT.  Am I using Swing without realizing  
it?  I understand that my reason for avoiding Swing is based on the Swing  
controls, and so as long as I'm not using those the other parts of Swing  
aren't actually something I need to avoid (it's not like I'm looking to  
avoid linking to some library or something like that :) ).  But I'm a bit  
confused about where the line between AWT and Swing is drawn, if at all.

As far as the specific example goes...

While I'm not exactly clear on why they didn't just allow the paint()  
method to be overloaded, I do admit it provides a simpler API.  But at the  
very least, the docs should actually _say_ what is being passed to the  
paint() method.  (By docs, I'm talking about this:  
http://java.sun.com/javase/6/docs/api/ ...that's what I've been using as  
my reference).

For example, the page for Graphics2D might have mentioned it somewhere in  
the lengthy discussion describing drawing in Java.  Or the page for the  
Component class (where paint() is declared) might mentioned that the  
system will pass a Graphics2D as the parameter, at least on Java versions  
recent enough to do that.  Or maybe it would at least have mentioned it in  
the article entitled "Painting in AWT and Swing"  
(http://java.sun.com/products/jfc/tsc/articles/painting/index.html).

But I haven't found a single mention of the exact behavior of the  
implementation anywhere in what I think are the official Java docs.

Anyway, thanks very much for the information.  I've actually run into  
other oddities that, while not preventing me from implementing the code  
the way I want to, do have me scratching my head now and then.  Maybe if  
they keep puzzling me, I'll post those questions too, eventually.  :)

Pete
RedGrittyBrick - 09 Jan 2008 11:33 GMT
> Okay, so bottom line: no implicit type conversions (that is, something
> that actually modifies the data) for reference types.  Only straight
> casting.

There is always explicit type conversion. For example List.toArray() or
Integer.toString();

> From what I've read, Swing reimplements all of the
> controls and always will look the same regardless of the host OS).

You can use a system Look and Feel so that the application looks
(almost) like a native application on (almost) any platform.

  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

> Graphics and Graphics2D are both in java.awt, and I just assumed that
> Graphics2D was actually part of AWT.  Am I using Swing without realizing
> it?  

Probably not, java.awt.Graphics2D is AWT not Swing. AIUI Swing uses a
lot of AWT but that doesn't make AWT Swing.

javax.swing.Graphics2D would be Swing if it existed. But then you'd know
you were using Swing.

> I'm a bit confused about where the line between AWT and Swing is
> drawn, if at all.

I bet Roedy's web site has a page on this.

Swing is built on AWT. For example look at
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JMenuBar.html
  java.lang.Object
     java.awt.Component
        java.awt.Container
           javax.swing.JComponent
              javax.swing.JMenuBar
Many Swing Objects are descended from AWT objects. AIUI the reverse
never applies.

When you write a Swing application you end up using a lot of AWT
objects. For example Swing's JMenu.setMargin() takes an AWT
java.awt.Margin parameter. AIUI the reverse never applies.

In practice, when using an IDE like Eclipse or NetBeans, you never have
to worry about this IME.

A rule of thumb is that all Swing visual components have names starting
with the letter J. So far as I know, I've never accidentally inserted an
an AWT TextField instead of a Swing JTextField into a Swing GUI.
Roedy Green - 10 Jan 2008 07:53 GMT
On Wed, 09 Jan 2008 11:33:23 +0000, RedGrittyBrick
<RedGrittyBrick@SpamWeary.foo> wrote, quoted or indirectly quoted
someone who said :

>> I'm a bit confused about where the line between AWT and Swing is
>> drawn, if at all.
>
>I bet Roedy's web site has a page on this.

See http://mindprod.com/jgloss/swing.html#AWTEQUIVALENTS
for a table of AWT and Swing equivalents.

and a list of differences between them.

Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Arne Vajhøj - 19 Jan 2008 05:05 GMT
> I made a specific choice to try to avoid Swing.  The program I'm writing
> isn't going to use any advanced controls anyway, and I'd prefer that
[quoted text clipped - 8 lines]
> understand it.  From what I've read, Swing reimplements all of the
> controls and always will look the same regardless of the host OS).

Have you tried playing with look and feel.

The demo program below illustrates.

Arne

=============================================

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class MultiLookAndFeel extends JFrame implements ActionListener {
  private JButton windows = new JButton("Windows");
  private JButton motif = new JButton("Motif");
  private JButton metal1 = new JButton("Metal/ocean");
  private JButton metal2 = new JButton("Metal/steel");
  private JButton gtk = new JButton("GTK");
  private JButton java = new JButton("Java");
  private JButton system = new JButton("System");
  public MultiLookAndFeel() {
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      getContentPane().setLayout(new GridLayout(7, 1));
      windows.addActionListener(this);
      getContentPane().add(windows);
      motif.addActionListener(this);
      getContentPane().add(motif);
      metal1.addActionListener(this);
      getContentPane().add(metal1);
      metal2.addActionListener(this);
      getContentPane().add(metal2);
      //gtk.addActionListener(this);
      getContentPane().add(gtk);
      java.addActionListener(this);
      getContentPane().add(java);
      system.addActionListener(this);
      getContentPane().add(system);
      pack();
  }
  public void actionPerformed(ActionEvent e) {
      try {
        if(e.getSource() == windows) {

UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } else if(e.getSource() == motif) {

UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
        } else if(e.getSource() == metal1) {
            javax.swing.plaf.metal.MetalLookAndFeel.setCurrentTheme(new
javax.swing.plaf.metal.OceanTheme());

UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        } else if(e.getSource() == metal2) {
            javax.swing.plaf.metal.MetalLookAndFeel.setCurrentTheme(new
javax.swing.plaf.metal.DefaultMetalTheme());

UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        } else if(e.getSource() == gtk) {

UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
        } else if(e.getSource() == java) {

UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
        } else if(e.getSource() == system) {

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
      } catch (ClassNotFoundException e1) {
        e1.printStackTrace();
      } catch (InstantiationException e1) {
        e1.printStackTrace();
      } catch (IllegalAccessException e1) {
        e1.printStackTrace();
      } catch (UnsupportedLookAndFeelException e1) {
        e1.printStackTrace();
      }
      SwingUtilities.updateComponentTreeUI(this);
      pack();
  }
  public static void main(String[] args) {
      MultiLookAndFeel f = new MultiLookAndFeel();
      f.setVisible(true);
  }
}
Roedy Green - 09 Jan 2008 10:16 GMT
On Tue, 08 Jan 2008 22:07:33 -0800, "Peter Duniho"
<NpOeStPeAdM@nnowslpianmk.com> wrote, quoted or indirectly quoted
someone who said :

>My apologies if this is a silly question in the context of Java.  I'm very  
>new to the language, though I've got lots of experience in others  
>(including C#, which has borrowed a lot from Java) and programming  
>generally.

My essay might help explain this:

http://mindprod.com/jgloss/cast.html
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Hal Rosser - 09 Jan 2008 20:03 GMT
> My apologies if this is a silly question in the context of Java.  I'm very
> new to the language, though I've got lots of experience in others
[quoted text clipped - 22 lines]
>     * Or will the code fail if it's run in an environment where a plain
> Graphics instance is passed?

The getClass() method of the Object class and the getName() method of the
Class class along with the typeOf operator may be of some help in your
quest.
HTH
Hal
Peter Duniho - 09 Jan 2008 20:17 GMT
> The getClass() method of the Object class and the getName() method of the
> Class class along with the typeOf operator may be of some help in your  
> quest.

Thanks!  I was more looking for a discussion of the rules governing what  
types may be passed or returned in contexts where a base type is specified  
but a derived type is actually provided.  However, your information about  
run-time type checking is very useful as well.  I probably could've found  
it myself in the docs, but having it handed over to me without me having  
to work for it is very nice.  :)

Pete
Patricia Shanahan - 09 Jan 2008 21:15 GMT
>> The getClass() method of the Object class and the getName() method of the
>> Class class along with the typeOf operator may be of some help in
[quoted text clipped - 8 lines]
>
> Pete

Also, there is the "instanceof" operator:

if(x instanceof Graphics2D){
  Graphics2D y = (Graphics2D)x;
  // Do Graphics2D things with y
}else{
  // Do something else that only needs Graphics
}

Patricia


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.