Polymorphism in Java SE?

S

Stefan Ram

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.
 
M

Mark Rafn

Stefan Ram said:
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
{
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«).

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.
 
E

Eric Sosman

Stefan said:
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.
[...]

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, ...
 
A

Arne Vajhøj

Stefan said:
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.

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

Arne
 
K

Karl

Stefan Ram said:
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.

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.
 
M

Mark Space

Stefan said:
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
 
P

Patricia Shanahan

Stefan Ram wrote:
....
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
 
S

Stefan Ram

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/...se(java.lang.String, java.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.
 
S

Stefan Ram

Patricia Shanahan said:
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.)
 
P

Patricia Shanahan

Stefan said:
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«.


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.

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
 
P

Patricia Shanahan

Stefan said:
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).

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
 
H

Hal Rosser

Stefan Ram said:
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/...se(java.lang.String, java.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.

public static Object firstElement( Object[] o){
return o[0];
}
 
M

Mark Space

Patricia said:
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.
 
M

Michael Jung

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
 
S

Stefan Ram

Michael Jung said:
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
{ ... }}
 
L

Lew

Stefan said:
Michael Jung said:
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
{ ... }}
 
L

Lew

Michael Jung said:
What is missing/excess in:
Number x = NumberFormat.getInstance().parse(argv[0]);
Stefan said:
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.
 
R

Roedy Green

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.
 
L

Lew

Arne said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top