Type conversion for reference types?

Discussion in 'Java' started by Peter Duniho, Jan 9, 2008.

  1. Peter Duniho

    Peter Duniho Guest

    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
     
    Peter Duniho, Jan 9, 2008
    #1
    1. Advertising

  2. Peter Duniho

    Stefan Ram Guest

    "Peter Duniho" <> writes:
    >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, Jan 9, 2008
    #2
    1. Advertising

  3. Peter Duniho wrote:
    > 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


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

    --

    Knute Johnson
    email s/nospam/knute/

    --
    Posted via NewsDemon.com - Premium Uncensored Newsgroup Service
    ------->>>>>>http://www.NewsDemon.com<<<<<<------
    Unlimited Access, Anonymous Accounts, Uncensored Broadband Access
     
    Knute Johnson, Jan 9, 2008
    #3
  4. Peter Duniho

    Lew Guest

    Peter Duniho wrote:
    > 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.

    --
    Lew
     
    Lew, Jan 9, 2008
    #4
  5. Peter Duniho

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >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«.
     
    Stefan Ram, Jan 9, 2008
    #5
  6. Peter Duniho

    Peter Duniho Guest

    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:

    On Tue, 08 Jan 2008 22:32:10 -0800, Lew <> wrote:

    > [...]
    >> * 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
     
    Peter Duniho, Jan 9, 2008
    #6
  7. Peter Duniho

    Roedy Green Guest

    On Tue, 08 Jan 2008 22:07:33 -0800, "Peter Duniho"
    <> 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
    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
     
    Roedy Green, Jan 9, 2008
    #7
  8. Peter Duniho wrote:
    > 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.
     
    RedGrittyBrick, Jan 9, 2008
    #8
  9. Peter Duniho

    Hal Rosser Guest

    "Peter Duniho" <> wrote in message
    news:eek:...
    > 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 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
     
    Hal Rosser, Jan 9, 2008
    #9
  10. Peter Duniho

    Peter Duniho Guest

    On Wed, 09 Jan 2008 12:03:25 -0800, Hal Rosser <>
    wrote:

    > 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
     
    Peter Duniho, Jan 9, 2008
    #10
  11. Peter Duniho wrote:
    > On Wed, 09 Jan 2008 12:03:25 -0800, Hal Rosser <>
    > wrote:
    >
    >> 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


    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
     
    Patricia Shanahan, Jan 9, 2008
    #11
  12. Peter Duniho

    Roedy Green Guest

    On Wed, 09 Jan 2008 11:33:23 +0000, RedGrittyBrick
    <> 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.

    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
     
    Roedy Green, Jan 10, 2008
    #12
  13. Peter Duniho wrote:
    > 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).


    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);
    }
    }
     
    Arne Vajhøj, Jan 19, 2008
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stefan Strasser
    Replies:
    2
    Views:
    8,168
    Victor Bazarov
    Mar 28, 2005
  2. Replies:
    3
    Views:
    819
  3. ittium
    Replies:
    4
    Views:
    303
    Goran
    Dec 9, 2011
  4. Sam Kong
    Replies:
    12
    Views:
    294
    John G Harris
    Oct 17, 2006
  5. Russel Walker
    Replies:
    1
    Views:
    104
    Steven D'Aprano
    Jun 27, 2013
Loading...

Share This Page