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 2007

Tip: Looking for answers? Try searching our database.

Polymorphism in Java SE?

Thread view: 
Stefan Ram - 22 Dec 2007 18:44 GMT
For teaching purposes, I'd like to know a Java-SE method
 that returns an object whose class is only known at runtime
 and can be shown to have at least two possibly values by
 running a small program.

 It would be best if this would be a static method that can
 be called without any preparation.

 For example, it would be great, if Java SE had an »input« method,
 which returned »java.lang.Integer« or »java.lang.String«
 depending on the text typed in the console.

 Then I could write:

public class Main
{
 public static void main
 ( final java.lang.String[] args )
 {
   java.lang.System.out.println
   ( java.lang.System.in.input().getClass() ); }}

 Which would print »java.lang.Integer« (when one
 enters »123«) or »java.lang.String« (when one enters »abc«).

 However, I am not aware of such a method.

 The usual approach is to put objects of different classes
 into a heterogeneous container, then reading them in again,
 and - surprise! - get objects of different classes.

 I wonder, if it can get any simpler, without a container,
 without preparation.

 A near miss is the field »System.in«, which indeed contains an
 object of a proper /subtype/ of the field's type. So it is
 somewhat polymorphic. You do not know the actual type until
 run-time. It is only boring insofar as it is always the same
 subtype.

 Possibly, somewhere in the huge Java-SE API there is a little
 known field or method I could use.
Mark Rafn - 22 Dec 2007 19:41 GMT
>  For teaching purposes, I'd like to know a Java-SE method
>  that returns an object whose class is only known at runtime
>  and can be shown to have at least two possibly values by
>  running a small program.

Doesn't this describe just about any factory method?  This seems to be pretty
fundamental to the point of interfaces, and you should be able to find or
create dozens of examples.

>  It would be best if this would be a static method that can
>  be called without any preparation.

Calendar.getInstance returns a Calendar object that's actually a subclass, for
instance.  Swing's UIManager.getLookAndFeel() will return a different
LookAndFeel subclass depending on platform and settings.

In both cases (and most useful cases of this), there's a common parent type
that all returned types will extend or implement, so the caller doesn't
actually have to do instanceof - just use the methods on the parent type.

That's what polymorphism is intended for.  If you're calling instanceof,
you're likely doing something a bit odd.

>  For example, it would be great, if Java SE had an »input« method,
>  which returned »java.lang.Integer« or »java.lang.String«
>  depending on the text typed in the console.

1) If you think this would be great, write one.  It's probably not more than a
dozen lines of code.  

2) I think this would be less great than you think.  It's rare that you want
to have random objects without a useful parent class/interface by which you
handle them all.

>public class Main
>{
[quoted text clipped - 6 lines]
>  Which would print »java.lang.Integer« (when one
>  enters »123«) or »java.lang.String« (when one enters »abc«).

In practice, you ALWAYS want the String, then parse it to a more specific
type, with error handling and fallback in a type-safe way.  

>  The usual approach is to put objects of different classes
>  into a heterogeneous container, then reading them in again,
>  and - surprise! - get objects of different classes.

Huh?  You still only get out what you put in.  And you don't need a container,
just use a variable.  "Object o" can be any reference type.

>  Possibly, somewhere in the huge Java-SE API there is a little
>  known field or method I could use.

For teaching purposes, why not write (or have students write) it?  Something
like:

 /*
  * parse a String, returning a String, Boolean, or Integer, depending on
  * the contents of the string.  Returns null for null input.
  */
 public static Object parseString(String input) {
   if (input == null)
       return null;

   try {
       // attempt to parse as int.  if success, return it.
       return new Integer(Integer.parseInt(input));
   } catch (NumberFormatException nfe) { }
   if ("true".equals(input))
       return Boolean.TRUE;
   else if ("false".equals(input))
       return Boolean.FALSE;
   else
       return input;
 }

Keep in mind that this is a crappy thing to do most of the time.  You're going
to force users of this method to basically have the same if/else if/else logic
you have here, except with instanceof instead of testing directly.  
--
Mark Rafn    dagon@dagon.net    <http://www.dagon.net/>
Eric Sosman - 22 Dec 2007 19:52 GMT
>   For teaching purposes, I'd like to know a Java-SE method
>   that returns an object whose class is only known at runtime
[quoted text clipped - 4 lines]
>   be called without any preparation.
> [...]

    Use Collections.unmodifiableList() on a List reference that
is made to refer to various kinds of Lists:

    List list = new ArrayList();
    Class c1 = Collections.unmodifiableList(list).getClass();
    list = new LinkedList();
    Class c2 = Collections.unmodifiableList(list).getClass();
    list = Arrays.asList(argsOfMain);
    Class c3 = Collections.unmodifiableList(list).getClass();

    Maybe not compelling enough, because even though the List-ness
of list doesn't determine the class of the unmodifiable wrapper,
the actual nature of the object it refers to does.  Maybe a more
direct example would be to use the parse() method of a NumberFormat
and show that sometimes it returns a Long and sometimes a Double.

    A slightly different wrinkle: Catch an IOException and show
that different kinds of run-time failures generate different
subclasses: FileNotFoundException, EOFException, ...

Signature

Eric Sosman
esosman@ieee-dot-org.invalid

Arne Vajhøj - 22 Dec 2007 20:02 GMT
>   For teaching purposes, I'd like to know a Java-SE method
>   that returns an object whose class is only known at runtime
[quoted text clipped - 3 lines]
>   It would be best if this would be a static method that can
>   be called without any preparation.

A well known and not that difficult to setup example
would be DriverManager.getConnection.

Arne
Lew - 24 Dec 2007 02:25 GMT
>>   For teaching purposes, I'd like to know a Java-SE method
>>   that returns an object whose class is only known at runtime
[quoted text clipped - 6 lines]
> A well known and not that difficult to setup example
> would be DriverManager.getConnection.

Or, for that matter, Class.forName( dbDriverName ).

It's quite common to read in the driver name from a deployment descriptor.
It's easy to tell if the wrong one loaded in for either of these cases - the
database connection creation fails.

Signature

Lew

Karl - 22 Dec 2007 22:29 GMT
>  For teaching purposes, I'd like to know a Java-SE method
>  that returns an object whose class is only known at runtime
[quoted text clipped - 38 lines]
>  Possibly, somewhere in the huge Java-SE API there is a little
>  known field or method I could use.

From your post, I am not sure if you are really more interested in
polymorphism or reflection. If it is really polymorphism you are interested
in, java.lang.Number is a perfectly good example. All of the Java primitive
numeric wrappers extend Number, and you can get the value in any primitive
form, plus as a String, just by calling the methods on the base class. You
don't need to have any idea what object you are using. Taking it even a bit
further, all Java objects extend object, which provides polymorphic methods
for synchronization, hash functions and comparison, and toString.

Your program/method could create Float, Integer, Short, etc., based on a
user input string, and return a Number.

If you want reflection with a polymorphic outcome, why not just use
java.lang.Class.forName and newInstance? The Object instance you will get
back will be as polymorphic as you want it to be. It will return type T of
the Class you are using to create the instance. This is the usual way to
create instances whose types are not known, or even conceived of, until
run-time.

Your program/method could create whatever type the user enters on the
command line (e.g., "java.lang.String") and return an Object. An exercise
for the student would be figuring out how to create new instances of classes
that do not have a zero-arg constructor.
Karl - 22 Dec 2007 22:40 GMT
Oops -- I got carried away -- java.lang.Object is not comparable. Sorry
about that.
Mark Space - 22 Dec 2007 23:06 GMT
>   For teaching purposes, I'd like to know a Java-SE method
>   that returns an object whose class is only known at runtime
>   and can be shown to have at least two possibly values by
>   running a small program.

Here's my entry.  I make some Swing components, then print out their
actual type.  Swing makes heavy use of polymorphism, and does so for
good reasons.  It's overall an excellent case study for students.

First I make a simple JOptionDialog.  Then I print out all of the types
that it contains.  The method which returns the components says they
should be all of type Component, but actually their all different,
descendant types.

You'll need to fix up the line breaks a bit.  Output follows.

package polymorphism;

import java.awt.Component;
import java.awt.Container;
import javax.swing.JOptionPane;

/** Check the insides of a JFileChooser.
 * <p>
 * This will demonstrate the use of polymorphism in Java.
 */
public class PolyCheck {

    /** Called from the command line.
     *
     * @param args the command line arguments are igonred.
     */
    public static void main(String[] args) {
        // TODO code application logic here
        final JOptionPane optionPane = new JOptionPane(
                "The only way to close this dialog is by\n" +
                "pressing one of the following buttons.\n" +
                "Do you understand?",
                JOptionPane.QUESTION_MESSAGE,
                JOptionPane.YES_NO_OPTION);

        // First polymorphism: optionPane is a JOptionPane but we can
// treat
        // it like a Container.

        printComponents(optionPane, 0);

    }

    public static void printComponents(Container cont, int offset) {

        Component[] comps = cont.getComponents();

        // comps should be all Components, but let's see what they
// really are.

        for (Component c : comps) {
            System.out.println( repeat( " ",offset*4
)+c.getClass().getName());
            if( c instanceof Container ) {
                printComponents( (Container)c, offset+1 );
            }
        }
    }

    public static String repeat( String s, int times ) {
        StringBuffer sb = new StringBuffer();
        for( int i = 0; i < times; i++ ) {
            sb.append( s );
        }
        return sb.toString();
    }
}

---------------------
Output:
javax.swing.JPanel
    javax.swing.JPanel
        javax.swing.JPanel
        javax.swing.JPanel
            javax.swing.JLabel
            javax.swing.JLabel
            javax.swing.JLabel
    javax.swing.JLabel
javax.swing.JPanel
    javax.swing.JButton
    javax.swing.JButton
Patricia Shanahan - 22 Dec 2007 23:10 GMT
...
>   A near miss is the field »System.in«, which indeed contains an
>   object of a proper /subtype/ of the field's type. So it is
>   somewhat polymorphic. You do not know the actual type until
>   run-time. It is only boring insofar as it is always the same
>   subtype.
...

Huh? Why do you say it is always the same subtype?

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class SystemDotInClasses {
  public static void main(String[] args) throws IOException {
    System.out.println("Initial class: "
        + System.in.getClass().getName());
    String someData = "xyzzy";
    InputStream someStream = new ByteArrayInputStream(
        someData.getBytes());
    System.setIn(someStream);
    System.out.println("Second class: "
        + System.in.getClass().getName());
    int firstByte = System.in.read();
    if (firstByte == -1) {
      System.out.println("Empty input");
    } else {
      System.out.println("First byte of input: "
          + (char) firstByte);
    }
    ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
    DataOutputStream out = new DataOutputStream(outBytes);
    out.writeDouble(Math.PI);
    someStream = new DataInputStream(
        new ByteArrayInputStream(outBytes.toByteArray()));
    System.setIn(someStream);
    System.out.println("Third class: "
        + System.in.getClass().getName());
    double d = ((DataInputStream) System.in).readDouble();
    System.out.println("Read from data stream " + d);
  }
}

Patricia
Stefan Ram - 22 Dec 2007 23:32 GMT
>>A near miss is the field »System.in«, which indeed contains an
>>object of a proper /subtype/ of the field's type. So it is
>>somewhat polymorphic. You do not know the actual type until
>>run-time. It is only boring insofar as it is always the same
>>subtype.
>Huh? Why do you say it is always the same subtype?

 Said »always the same subtype«,
 thought »always the same subtype at the start of a program«.

 Sorry, I should also have written »at the start of a program«.

>System.setIn(someStream);

 Yes, indeed. This is possible. Thank you.

 Here one party (your code) sets the field and then /the same
 party/ reads it in again. I believe it might be more
 suggestive when polymorphism is used for communication between
 /two/ parties. Therefore, I searched for a Java-SE factory
 method, so that I can show, how Java SE conveys information to
 an application by a polymorphic expression.

 (I have not yet acknowledged Marks post in my previous post,
 because I had not read it then. So I'd also like to thank him
 for the Swing example.)
Patricia Shanahan - 22 Dec 2007 23:59 GMT
>>> A near miss is the field »System.in«, which indeed contains an
>>> object of a proper /subtype/ of the field's type. So it is
[quoted text clipped - 18 lines]
>   method, so that I can show, how Java SE conveys information to
>   an application by a polymorphic expression.

Indeed. The program I posted was just intended to demonstrate some of
the System.in possibilities.

To use this to demonstrate polymorphism, I would write some simple
method that reads from System.In and uses the data to do its job. I
would then write two main programs to control it, one using standard
input and the other forcing a different data source.

This approach can be useful, for example, for testing a class that
normally reads from standard input. The test code can force its own data
using System.setIn.

Patricia
Stefan Ram - 22 Dec 2007 23:11 GMT
>For teaching purposes, I'd like to know a Java-SE method
>that returns an object whose class is only known at runtime

 Thanks for the answers so far!

 Why do I not write a custom method or class for this?

 I have this idea that teaching should go from the simple
 things to more advanced things. To me, /using/ objects of
 JAVA-SE classes is more simple than /declaring/ custom classes
 (eating is more simple than designing a dish and cooking it).

 Therefore, when I introduce objects and their properties,
 I have not yet introduced class or non-static method
 declarations: Most statements still go into the body of
 the static »main« method.

 So, at this point, I would like to show how to /use/
 polymorphic designs, but not yet how to create a new
 design.

 »DriverManager.getConnection()« might be of no use when used
 in isolation and a full JDBC client might be too large at this
 point.

 To use the parse() method of a NumberFormat (Eric)

http://download.java.net/jdk7/docs/api/java/text/NumberFormat.html#parse(java.la
ng.String,%20java.text.ParsePosition
)

 , is very close to what I was looking for.

 I will also look into catching an IOException,
 Calendar.getInstance(), java.lang.Class.forName and
 newInstance and other suggestions.

 One example I already use, but which looks somewhat contrived
 and not like the solution of any real problem is:

( Math.random() > .5 ? System.out : "example" ).hashCode()

 This is simple: No containers, no declarations, just
 polymorphism. There is an expression for an object whose
 type is only known at run time and a verb »hashCode«, which
 indeed has two completely different implementations in
 both cases. This is good so far.

 The problem is: This example makes no real sense: One can not
 imagine that one really needs this specific expression to
 solve any problem. So I am looking for something as simple and
 polymorphic as this but with more sense. Possibly I can use
 the abovementioned »parse« verb for this.
Patricia Shanahan - 23 Dec 2007 00:02 GMT
>> For teaching purposes, I'd like to know a Java-SE method
>> that returns an object whose class is only known at runtime
[quoted text clipped - 7 lines]
>   JAVA-SE classes is more simple than /declaring/ custom classes
>   (eating is more simple than designing a dish and cooking it).

However, you may be trying to teach relatively advanced concepts too
soon. I don't really get programming ideas until I start using them in
my own code. Maybe you should wait to teach about polymorphism until it
comes up naturally in your students' programming.

Patricia
Mark Space - 23 Dec 2007 05:41 GMT
> However, you may be trying to teach relatively advanced concepts too
> soon. I don't really get programming ideas until I start using them in
> my own code. Maybe you should wait to teach about polymorphism until it
> comes up naturally in your students' programming.

I was going to make the same comment. I'd teach language basics first,
then static vs. instance methods and variables.  Once the people in the
classroom seems to grasp that, then add polymorphism.

I don't think anyone will truly understand what's going on with
variables changing type (via polymorphism) unless they had a chance to
make some types themselves and got to practice "AClass ac = new
AClass()" a lot first.

Trying to show everyone "Look! See! Polymorphism!" before they're really
understood (and practiced) some types for themselves seems like it just
wouldn't really make an impression.  A simple example might be a good
way to lead off the lecture on polymorphism though, once the class
arrived at that point.
Hal Rosser - 23 Dec 2007 00:10 GMT
>>For teaching purposes, I'd like to know a Java-SE method
>>that returns an object whose class is only known at runtime
[quoted text clipped - 47 lines]
>  polymorphic as this but with more sense. Possibly I can use
>  the abovementioned »parse« verb for this.

public static Object  firstElement( Object[] o){
   return o[0];
}
Michael Jung - 23 Dec 2007 10:16 GMT
> > For teaching purposes, I'd like to know a Java-SE method
> > that returns an object whose class is only known at runtime
> To use the parse() method of a NumberFormat (Eric)
> is very close to what I was looking for.

Why doesn't this solve your problem completely? What is missing/excess
in:

   static public void main(String[] argv) {
       try {
           Number x = NumberFormat.getInstance().parse(argv[0]);
           System.out.println(x.getClass());
       }
       catch (ParseException e) {
           System.out.println("Cheating...");
       }
   }

Michael
Stefan Ram - 23 Dec 2007 16:12 GMT
>>To use the parse() method of a NumberFormat (Eric)
>>is very close to what I was looking for.
>Why doesn't this solve your problem completely?

 In fact, it might be so close to what I was looking
 for that I can not tell the difference.
 (The only thing simpler might be a static method.)

>What is missing/excess in:
>Number x = NumberFormat.getInstance().parse(argv[0]);

 A slight excess here is »getInstance()«.
 A hypothetical »NumberFormat.parse(...)« would be simpler.

>catch (ParseException e)

 At this point I have not yet taught exceptions.

 I am using a »frame« for the first lessons which looks like

public class Main
{ public static void main( final java.lang.String[] args )
 { ... }}

 The students are asked to use this frame for some lessons
 accepting that not all details of it have been explained yet.

 Possibly, that frame should more generally be:

public class Main
{ public static void main( final java.lang.String[] args )
 throws java.lang.Exception
 { ... }}
Lew - 23 Dec 2007 17:27 GMT
>>> To use the parse() method of a NumberFormat (Eric)
>>> is very close to what I was looking for.
[quoted text clipped - 29 lines]
>   throws java.lang.Exception
>   { ... }}

Signature

Lew

Lew - 23 Dec 2007 17:31 GMT
Michael Jung <miju@golem.phantasia.org> writes:
>>> What is missing/excess in:
>>> Number x = NumberFormat.getInstance().parse(argv[0]);

Stefan Ram wrote:
>>   A slight excess here is »getInstance()«.
>>   A hypothetical »NumberFormat.parse(...)« would be simpler.

No excess.  It has to have an instance so that different format objects can do
different things.  A "hypothetical »NumberFormat.parse(...)«" would destroy
the usefulness of the class.

Note that the static methods are getInstance(), getCurrencyInstance(),
getIntegerInstance(), getInstance( Locale local ), getNumberInstance(),
getPercentInstance().  Note further that the instances can be further modified
with all those lovely setXxx() methods.  A static parse() would defeat all of
that and turn NumberFormat into an unusable singleton.

Signature

Lew

Roedy Green - 23 Dec 2007 20:10 GMT
>  For teaching purposes, I'd like to know a Java-SE method
>  that returns an object whose class is only known at runtime
>  and can be shown to have at least two possibly values by
>  running a small program.

the most common one is readObject which reads from  an Object Stream,
but it would require a small file to read.
Signature

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



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.