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 / December 2005

Tip: Looking for answers? Try searching our database.

upcast: I have lost my example

Thread view: 
Stefan Ram - 28 Nov 2005 23:40 GMT
 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.
Thomas Hawtin - 29 Nov 2005 00:13 GMT
>   When someone asked me "When is an explicit upcast needed?",
>   I responded with the expression
[quoted text clipped - 7 lines]
>
>   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
[quoted text clipped - 21 lines]
>   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
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Stefan Ram - 29 Nov 2005 10:33 GMT
>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.
Thomas Hawtin - 29 Nov 2005 18:19 GMT
>   For this example, I would like to use a subset of Java that
>   excludes declarations.
[quoted text clipped - 3 lines]
>   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
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Stefan Ram - 29 Nov 2005 22:44 GMT
>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!
Chris Uppal - 30 Nov 2005 09:04 GMT
>   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
Stefan Ram - 30 Nov 2005 10:26 GMT
>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.
Chris Uppal - 30 Nov 2005 17:24 GMT
> > String s1 = new String(hi);    // works
> > String s2 = new String((Object) hi); // oops!
[quoted text clipped - 3 lines]
>   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
Stefan Ram - 30 Nov 2005 22:57 GMT
>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.
Chris Uppal - 01 Dec 2005 14:18 GMT
>   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
Thomas Hawtin - 29 Nov 2005 19:25 GMT
>>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
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Chris Uppal - 29 Nov 2005 11:22 GMT
>   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 - 29 Nov 2005 11:53 GMT
I wrote:

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

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

   -- chris
Stefan Ram - 29 Nov 2005 11:56 GMT
>Sorry, please ignore that.

 OK, then please also ignore my other reply to that.
Stefan Ram - 29 Nov 2005 13:45 GMT
>>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 - 29 Nov 2005 11:54 GMT
>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).
 
Chris Uppal - 29 Nov 2005 15:46 GMT
> > 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
Roedy Green - 29 Nov 2005 18:01 GMT
>>((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.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.



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.