upcast: I have lost my example

Discussion in 'Java' started by Stefan Ram, Nov 28, 2005.

  1. Stefan Ram

    Stefan Ram Guest

    When someone asked me "When is an explicit upcast needed?",
    I responded with the expression

    Math.random() > 0.5 ?( Object )System.in : System.out

    Bue in Java 1.5 this upcast is not required anymore. So, the
    expression

    Math.random() > 0.5 ? System.in : System.out

    will compile under 1.5 and 1.6, but not under 1.3 and 1.4.

    So what would be an example of a situation where an explicit
    upcast of an expression with a reference type is required
    under Java 1.5 and 1.6?

    Preferably an example that uses standard methods and
    identifiers as above and does not require the declaration
    of additional identifiers [methods].

    I can think of:

    interface A {} interface B {} class C implements A,B {}

    public class Main
    { static void f( A a ){}
    static void f( B b ){}
    public static void main( final java.lang.String[] args )
    { f(( A )new C() ); }}

    Here the upcast "( A )" is required.

    However, this example needs to declare methods and a
    situation with two interfaces (multiple inheritance),
    I would prefer an example with a single class as the
    super type (single inheritance) and without the need
    to declare additional classes or methods.
     
    Stefan Ram, Nov 28, 2005
    #1
    1. Advertising

  2. Stefan Ram wrote:
    > When someone asked me "When is an explicit upcast needed?",
    > I responded with the expression
    >
    > Math.random() > 0.5 ?( Object )System.in : System.out
    >
    > Bue in Java 1.5 this upcast is not required anymore. So, the
    > expression
    >
    > Math.random() > 0.5 ? System.in : System.out
    >
    > will compile under 1.5 and 1.6, but not under 1.3 and 1.4.


    Good old^Wnew intersection types.

    > So what would be an example of a situation where an explicit
    > upcast of an expression with a reference type is required
    > under Java 1.5 and 1.6?
    >
    > Preferably an example that uses standard methods and
    > identifiers as above and does not require the declaration
    > of additional identifiers [methods].
    >
    > I can think of:
    >
    > interface A {} interface B {} class C implements A,B {}
    >
    > public class Main
    > { static void f( A a ){}
    > static void f( B b ){}
    > public static void main( final java.lang.String[] args )
    > { f(( A )new C() ); }}
    >
    > Here the upcast "( A )" is required.
    >
    > However, this example needs to declare methods and a
    > situation with two interfaces (multiple inheritance),
    > I would prefer an example with a single class as the
    > super type (single inheritance) and without the need
    > to declare additional classes or methods.


    Casting from Properties to Map<String,String>, or any other "impossible"
    cast (given a non-buggy compiler).

    Actually, you don't actually need the explicit cast. You could write:

    A c = new C();
    f(c);

    Tom Hawtin
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Nov 29, 2005
    #2
    1. Advertising

  3. Stefan Ram

    Stefan Ram Guest

    Thomas Hawtin <> writes:
    >Actually, you don't actually need the explicit cast. You could
    >write:
    >A c = new C();
    >f(c);


    For this example, I would like to use a subset of Java that
    excludes declarations.

    I would like to answer the question "When is an upcast
    needed?" and preferably do not want to assume that
    declarations are already known to the person asking the
    question.

    >Casting from Properties to Map<String,String>, or any other
    >"impossible" cast (given a non-buggy compiler).


    I am not able to derive an actual expression that will
    fail if the upcast is removed from this description.

    java.util.Properties implements Map<Object,Object>, but not
    Map<String,String>, so I wonder if a cast to
    "Map<String,String>" is an "upcast" at all in the sense
    required here, i.e., a cast to a base class.

    I am looking for an expression that needs an explicit cast
    of a subexpression to a base class of that subexpression.
    An example was

    Math.random() > 0.5?( java.lang.Object )System.in : System.out

    in Java 1.4. Here "System.in" is cast to a base class of
    java.io.InputStream, and the example does not require
    declarations in addition to the J2SE-API. Now I am looking
    for such an example in Java 1.5.
     
    Stefan Ram, Nov 29, 2005
    #3
  4. Stefan Ram

    Chris Uppal Guest

    Stefan Ram wrote:

    > So what would be an example of a situation where an explicit
    > upcast of an expression with a reference type is required
    > under Java 1.5 and 1.6?


    Two examples:

    1) You require a readable (by a programmer) representation of Strings which
    allows you to distinguish between equal but not identical instances.

    String s = //...
    ((Object)s).toString();

    2) You wish to pass an Object[] array to a varadic method as a single argument,
    rather than having it interpreted as a pre-packed valist of Objects:

    Method method = // reflective access to
    // java.util.Arrays.hashCode(Object[])
    Object[] data = //... the data
    Object hash = method.invoke(null, (Object)data);

    (Idea suggested by John Bollinger)

    -- chris
     
    Chris Uppal, Nov 29, 2005
    #4
  5. Stefan Ram

    Stefan Ram Guest

    "Chris Uppal" <-THIS.org> writes:
    >1) You require a readable (by a programmer) representation of Strings which
    >allows you to distinguish between equal but not identical instances.
    >String s = //...
    >((Object)s).toString();


    I used to believe that such a cast will only make the compiler
    check that the signature exists in the base class, but will
    not alter the run time behavior.

    public class Main
    { public static void main( final java.lang.String[] args )
    { java.lang.System.out.println( "a".toString() );
    java.lang.System.out.println((( java.lang.Object )"a" ).toString() ); }}

    Prints "a" twice, and the two expression statements seem to be
    compiled to the same byte code.

    To get the behavior you might have intended, I might use
    something like:

    public java.lang.String myToString( final java.lang.Object object )
    { return object.getClass().getName() + "@" +
    Integer.toHexString( System.identityHashCode( object )); }

    >Object hash = method.invoke(null, (Object)data);


    That might answer my question -- still I would like to know if
    someone knows any example even simpler (not using reflection).
     
    Stefan Ram, Nov 29, 2005
    #5
  6. Stefan Ram

    Chris Uppal Guest

    I wrote:

    > String s = //...
    > ((Object)s).toString();


    Sorry, please ignore that. The example is completely invalid (was thinking in
    a different language)

    -- chris
     
    Chris Uppal, Nov 29, 2005
    #6
  7. Stefan Ram

    Stefan Ram Guest

    "Chris Uppal" <-THIS.org> writes:
    >Sorry, please ignore that.


    OK, then please also ignore my other reply to that.
     
    Stefan Ram, Nov 29, 2005
    #7
  8. Stefan Ram

    Stefan Ram Guest

    "Chris Uppal" <-THIS.org> writes:
    >>String s = //...
    >>(Object)s).toString();

    >Sorry, please ignore that. The example is completely invalid
    >(was thinking in a different language)


    One does not have to change the language, however, to see
    that effect, one only needs to use "static":

    class A { public static void f()
    { java.lang.System.out.println( "A" ); }}

    class B extends A { public static void f()
    { java.lang.System.out.println( "B" ); }}

    public class Main
    { public static void main( final java.lang.String[] args )
    { new B().f();
    (( A )new B() ).f(); }}
     
    Stefan Ram, Nov 29, 2005
    #8
  9. Stefan Ram

    Chris Uppal Guest

    Stefan Ram wrote:

    > > Object hash = method.invoke(null, (Object)data);

    >
    > That might answer my question -- still I would like to know if
    > someone knows any example even simpler (not using reflection).


    Well that (as an example) doesn't actually /use/ reflection, it's just that
    java.reflect.Method.invoke() is the first example that came to mind of a
    varadic Object* method that uses all its arguments. You can do exactly the
    same sort of thing with printf().

    Object[] data = new Object[0];
    System.out.printf("%s%n", data);
    System.out.printf("%s%n", (Object)data);

    The first form fails at runtime (not enough arguments), the second runs fine.
    Hence the behaviour is different when the upcast is included.


    Another class of examples is when the upcast influences method resolution.
    Given:

    void aMethod(Object o) { ... }

    void aMethod(String s) { ... }

    a call to:

    aMethod((Object)"hello")

    will be resolved differently from a call to:

    aMethod("hello").

    I'll leave you to find a pre-existing example of such a pair of method
    definitions in the standard library, though.


    Come to think of it, completely different class of examples:

    void aMethod() { throw new Error(); }

    compiles fine, but:

    void aMethod() { throw (Throwable)(new Error()); }

    is rejected.

    -- chris
     
    Chris Uppal, Nov 29, 2005
    #9
  10. Stefan Ram

    Roedy Green Guest

    On 29 Nov 2005 11:54:34 GMT, -berlin.de (Stefan Ram)
    wrote, quoted or indirectly quoted someone who said :

    >>((Object)s).toString();

    >
    > I used to believe that such a cast will only make the compiler
    > check that the signature exists in the base class, but will
    > not alter the run time behavior.


    It executes the Object.toString virtual method which is overridden by
    String, which is defined as "this object (which is already a string!)
    is itself returned."

    In other words the dance does nothing but get you back to s in a
    round-about way.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
     
    Roedy Green, Nov 29, 2005
    #10
  11. Stefan Ram wrote:
    >
    > For this example, I would like to use a subset of Java that
    > excludes declarations.
    >
    > I would like to answer the question "When is an upcast
    > needed?" and preferably do not want to assume that
    > declarations are already known to the person asking the
    > question.


    You don't think that's putting the cart before the horse? From 1.5 casts
    of reference types should be a relatively obscure feature. Perhaps
    mostly seen in implementations of equals methods.

    Tom Hawtin
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Nov 29, 2005
    #11
  12. Stefan Ram wrote:
    > Thomas Hawtin <> writes:
    >>
    >>Casting from Properties to Map<String,String>, or any other
    >>"impossible" cast (given a non-buggy compiler).

    >
    >
    > I am not able to derive an actual expression that will
    > fail if the upcast is removed from this description.


    The statement:

    Map<String,String> map = (Map<String,String>)new Properties();

    should fail to compile, producing a message along the lines of:

    MapProp.java:4: inconvertible types
    found : java.util.Properties
    required: java.util.Map<java.lang.String,java.lang.String>
    Map<String,String> map = (Map<String,String>)new Properties();
    ^
    1 error

    However, Sun's 1.5 compiler appears to be buggy in this respect.
    Discussed in another thread yesterday.

    > java.util.Properties implements Map<Object,Object>, but not
    > Map<String,String>, so I wonder if a cast to
    > "Map<String,String>" is an "upcast" at all in the sense
    > required here, i.e., a cast to a base class.


    A cast to either Map or Object should be required (given a correct
    compiler).

    > I am looking for an expression that needs an explicit cast
    > of a subexpression to a base class of that subexpression.
    > An example was
    >
    > Math.random() > 0.5?( java.lang.Object )System.in : System.out


    The expression

    new StringBuffer().append((Object)new char[] { '?' })

    should give a different result without the cast, but still compile.


    I tried to create something really obscure using TreeMap.Entry, but failed.

    Tom Hawtin
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Nov 29, 2005
    #12
  13. Stefan Ram

    Stefan Ram Guest

    Thomas Hawtin <> writes:
    >You don't think that's putting the cart before the horse? From
    >1.5 casts of reference types should be a relatively obscure
    >feature. Perhaps mostly seen in implementations of equals
    >methods.


    My main reason to want to explain casts in my classes is to
    prepare the explanation of implicit type conversions and to
    introduce the concept of the modification of the type of an
    expression. So first, I would like to explain the concept of a
    type modification by:

    ( Object )"example"

    Then I will show how to name a reference

    final Object reference =( Object )"example";

    and eventually I will mention that here the upcast "( Object )"
    is not required, because it is implied:

    final Object reference = "example";

    But I believe having first seen the explicit upcast helps to
    visualize what is happening implicitly in the last case.

    Now, of course, people might ask "What does one need the
    upcast operator for?" - I then would like to show an example
    at a point in the tutorial where many concepts have not yet
    been introduced, not even arrays. (So I can not use the
    examples with arrays, which some authors have kindly suggested
    to me in this thread.)

    So I should best try to find an overloaded standard method
    with different behavior for an Object and a String argument.

    Thanks for all replys!
     
    Stefan Ram, Nov 29, 2005
    #13
  14. Stefan Ram

    Chris Uppal Guest

    Stefan Ram wrote:

    > So I should best try to find an overloaded standard method
    > with different behavior for an Object and a String argument.


    Why not the very-simple-indeed:

    String hi = "hello";
    String s1 = new String(hi); // works
    String s2 = new String((Object) hi); // oops!

    Personally, I suspect that might be confusing to many -- but then that (I also
    suspect) hints that this concept is not suitable for early introduction.

    -- chris
     
    Chris Uppal, Nov 30, 2005
    #14
  15. Stefan Ram

    Stefan Ram Guest

    "Chris Uppal" <-THIS.org> writes:
    >Why not the very-simple-indeed:
    >String hi = "hello";
    >String s1 = new String(hi); // works
    >String s2 = new String((Object) hi); // oops!


    This example can be used indeed to show that the cast does
    have an effect at all. However, when someone asks "what is
    it good for?" an example that would fail /without an upcast/
    would be even better.

    >Personally, I suspect that might be confusing to many -- but
    >then that (I also suspect) hints that this concept is not
    >suitable for early introduction.


    The sequence of topics in my tutorial was developed by me to
    be quite strictly sorted according to the dependency, so that
    every concept is introduced before it is required for another
    concept.

    Because I believe, that beginners should like to program
    something graphical, I try to teach things so that Swing
    can be introduced as soon as possible. So before the Swing
    chapter I teach in this sequence (the audience are people
    not expected to have ever programmed before):

    - primitive values, primitive types and literals
    - static method invocations and the message syntax
    "receiver.selector( arguments )" where "receiver"
    is a class
    - operators ("+", "/", ...)
    - expression statement, compound-statement, ?:-operator
    - writing static methods, classes with static methods,
    constants and static fields/variables
    - using objects and understanding reference types
    of expressions and objects
    - understanding the concepts of subtypes and interfaces
    - writing classes with non-static methods and fields,
    writing interfaces

    And then I can begin to teach how to build basic Swing-GUIs.

    A remarkable thing, for example, is that at this point I have
    not yet mentioned things like the if-, switch-statement or any
    loop-statements. Because of the limited time some things do
    not fit in the course and so I dropped those.
     
    Stefan Ram, Nov 30, 2005
    #15
  16. Stefan Ram

    Chris Uppal Guest

    Stefan Ram wrote:

    > > String s1 = new String(hi); // works
    > > String s2 = new String((Object) hi); // oops!

    >
    > This example can be used indeed to show that the cast does
    > have an effect at all. However, when someone asks "what is
    > it good for?" an example that would fail /without an upcast/
    > would be even better.


    Wouldn't the answer "not much" be better still ? After all, you are not aiming
    to introduce your students to all of the Java language, so I don't understand
    why you want to put emphasis on this particular (rather arcane) feature. Why
    mention upcasts at all ?


    > [...]
    > A remarkable thing, for example, is that at this point I have
    > not yet mentioned things like the if-, switch-statement or any
    > loop-statements.


    That's impressive. (Quite seriously. I have a sneaking suspicion that those
    features are overused by nearly all programmers -- including myself).

    -- chris
     
    Chris Uppal, Nov 30, 2005
    #16
  17. Stefan Ram

    Stefan Ram Guest

    "Chris Uppal" <-THIS.org> writes:
    >Why mention upcasts at all ?


    I was hoping that discussing explicit upcasts will help to
    understand implied type conversions done by Java, when an
    expression of a subtype is accepted at places where a value
    of a supertype is expected.
     
    Stefan Ram, Nov 30, 2005
    #17
  18. Stefan Ram

    Chris Uppal Guest

    Stefan Ram wrote:

    > I was hoping that discussing explicit upcasts will help to
    > understand implied type conversions done by Java, when an
    > expression of a subtype is accepted at places where a value
    > of a supertype is expected.


    Hmm. Well, you are a teacher, and I am not.

    I would have tried to explain that it's OK to assign a reference to a Float to
    a variable of type Number. (though, probably not in those words) and that the
    Float itself is unchanged, but the compiler "forgets" that it knew the object
    was a Float, and left it at that. To my mind that "it just works how you
    expect, you don't have to think about why" is pretty much the /central/ message
    of declaratively-typed OO programming.

    S) Can I assign a Float to a Number ?

    T) <surprised>Yes, of course. Why not ?

    S) <still puzzled> But I can't assign to a String to
    a Number, so how come it works with Floats ?

    T) Because everything you can do with a Number
    you can also do with a Float, so nobody cares
    if you use a Float instead of a Number.

    (if you see what I mean)

    -- chris
     
    Chris Uppal, Dec 1, 2005
    #18
    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. news.microsoft.com
    Replies:
    0
    Views:
    313
    news.microsoft.com
    Apr 15, 2005
  2. Peter Ashford

    Re: Need to upcast?

    Peter Ashford, Jul 22, 2003, in forum: Java
    Replies:
    3
    Views:
    2,331
    Peter Ashford
    Jul 23, 2003
  3. Tobias K.
    Replies:
    16
    Views:
    5,287
    Mike Schilling
    Nov 22, 2004
  4. POLO TSHIRT
    Replies:
    0
    Views:
    197
    POLO TSHIRT
    Nov 8, 2010
  5. Jeff Uchtman

    Really lost, need some input or an example.

    Jeff Uchtman, Feb 3, 2004, in forum: ASP General
    Replies:
    4
    Views:
    178
    Jeff Uchtman
    Feb 3, 2004
Loading...

Share This Page