Java has organized its vast library into packages:
// File: blah.java // // Author: ... // Import all classes in java.io: import java.io.*; // Import only the StringTokenizer in java.util: import java.util.StringTokenizer;
Java 1.1 (onwards) provides the following 15 "standard" packages:
Other packages will be added to the library of future versions.
It is important to understand the distinction between these two versions:
Consider the class java.lang.Math:
Math m = new Math(); // Won't compile.
public final class Math {
// Two constants:
public static final double E;
public static final double PI;
// Some class methods:
public static int abs (int i);
public static double abs (double x); // long and float versions
// also available
public static native double sin (double x);
public static native double cost (double x);
public static native double log (double x);
public static native double exp (double x);
public static native double sqrt (double x);
public static native double pow (double x, double y);
public static native long round (double);
}
The String class in java.lang implements some class methods and many instance methods:
public final class String implements Serializable {
// ...
}
Note: the Serializable
interface indicates that String
instances can be written to files using serialization
public String (byte[] b); // Ascii representation.
public static String valueOf (double d);
This converts a double into a String.
// Get the character at i-th position. public char charAt (int i); // Compare strings: return -1 (less), 0 (equals) or 1. public int compareTo (String s); // Does it end with suffix s? public boolean endsWith (String s); // Does the instance equal string s? public boolean equals (String s); // Ignore case in testing equality. public boolean equalsIgnoreCase (String s); // Number of characters. public int length(); // Replace all occurences of a character. public String replace (char old, char new); // Does it start with prefix s? public boolean startsWith (String s); // Convert to lowercase. public String toLowerCase (); // Convert to uppercase. public String toUpperCase (); // Remove blanks on either side, but // not in the middle. public String trim ();
Next, consider the class Object:
public class Object {
// Constructor.
public Object ();
// Test equality: really intended for
// overriding.
public boolean equals (Object obj);
// Get class information dynamically.
// Cannot be overridden.
public final native Class getClass();
// Compute a hashcode.
public native int hashCode();
// Convert to String. Intended to
// be overridden.
public String toString ();
// Bitwise copy if Cloneable interface
// is declared as implemented.
protected native Object clone ()
throws CloneNotSupportedException.
// For cleaning up. Meant to be
// overridden.
protected void finalize ()
throws Throwable;
// These are all for Thread synchronization:
public final native void notify ();
public final native void notifyAll ();
public final native void wait (long millis)
throws InterruptedException;
public final native void wait (long millis, long nanos)
throws InterruptedException;
public final native void wait ()
throws InterruptedException;
}
Note:
Consider next the class java.lang.Integer:
public final class Integer extends Number {
// Constructors.
// Constants.
// Class methods.
// Instance methods.
}
// Takes in the integer value. public Integer (int i); // Takes in a String and parses it. public Integer (String s) throws NumberFormat
// Largest possible integer. public static final int MAX_VALUE; // Smallest (most negative) integer. public static final int MIN_VALUE;
// Parses a String into an int. public static int parseInt (String s) throws NumberFormatException; // A base or radix can be specified. public static int parseInt (String s, int radix) throws NumberFormatException; // Convert int value to binary (String). public static String toBinaryString (int i); // Convert to hex. public static String toHexString (int i); // These are different from the standard toString(). public static String toString (int i); public static String toString (int i, int radix);
// Return the int as a double. public double doubleValue (); // equals() and toString() have // been overridden. public boolean equals (Object obj); public String toString ();
The class java.math.BigInteger can be used for arbitrary precision arithmetic.
Consider computing the powers of 2 using int's:
Here is how BigInteger can be used: (source file)
import java.math.*;
public class TestBig {
public static void main (String[] argv)
{
// Initialize.
int i = 1;
BigInteger I = new BigInteger ("1");
// We will need this constant.
BigInteger Two = new BigInteger ("2");
// Compute successive powers of 2.
for (int j=1; j<=64; j++) {
i = i * 2;
I = I.multiply (Two);
System.out.println ("2 to the power " + j);
System.out.println ("i = " + i);
System.out.println ("I = " + I);
System.out.print ("\n");
}
}
}
Note:
// Absolute value. public BigInteger abs (); // Comparison. public int compareTo (BigInteger I); // Usual arithmetic operations. public BigInteger add (BigInteger I); public BigInteger subtract (BigInteger I); public BigInteger multiply (BigInteger I); public BigInteger divide (BigInteger I); public BigInteger pow (int a); // Operations specific to integers. public BigInteger mod (BigInteger I); public BigInteger remainder (BigInteger I); // Overriding methods from Object. public boolean equals (Object obj); public String toString (); // Recover basic types. public int intValue (); public long longValue (); public double doubleValue ();
In-class Exercise 8.1: Write a program to print out numbers in the Fibonacci sequence. Print out the first 200 numbers in the sequence.
Micro-tutorial on Fibonacci numbers:
Java provides the class Date in package java.util to store a date.
For example, the following code (source file)
import java.util.*;
public class TestDate {
public static void main (String[] argv)
{
Date d = new Date ();
System.out.println (d);
}
}
creates a Date instance initialized to the current date and time, and prints it out:
Mon Oct 05 15:46:12 EDT 1998
In Java 1.0, you could set the date using a constructor:
Date d2 = new Date ("October 5, 1998");
System.out.println (d2);
However, this method is deprecated in Java 1.1.
Instead, you need to use the following library classes in combination:
(You can also use only Calendar and DateFormat, but using them is more complicated).
A simple creation of a date: (source file)
import java.util.*;
import java.text.*;
public class TestDate2 {
public static void main (String[] argv)
{
GregorianCalendar cal = new GregorianCalendar (
1998, // Year
GregorianCalendar.OCTOBER, // Month
5, // Day
14, // Hour of day (2 pm)
30, // Minutes
22 // Seconds
);
// Get a Date instance.
Date d = cal.getTime ();
// Print.
System.out.println (d);
}
}
Note:
GregorianCalendar cal = new GregorianCalendar (); cal.set ( 1998, // Year GregorianCalendar.OCTOBER, // Month 5, // Day 14, // Hour of day (2 pm) 30, // Minutes 22 // Seconds );
GregorianCalendar cal = new GregorianCalendar (); cal.set (Calendar.YEAR, 1998); cal.set (Calendar.MONTH, Calendar.OCTOBER); cal.set (Calendar.DAY_OF_MONTH, 5); cal.set (Calendar.HOUR_OF_DAY, 14); // Use this instead of // Calendar.HOUR cal.set (Calendar.MINUTE, 30); cal.set (Calendar.SECOND, 22); cal.set (Calendar.MILLISECOND, 13); // Get a Date instance. Date d = cal.getTime (); // Print. System.out.println (d);
More about GregorianCalendar:
public static final int JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER; public static final int MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; public static final int AM, PM;
public static final int ERA, YEAR, MONTH, WEEK_OF_MONTH, DATE, DAY_OF_WEEK, DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK_IN_MONTH, ZONE_OFFSET, AM_PM, HOUR, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND;
public static final int AD, BC;
For example: (source file)
import java.util.*;
import java.text.*;
public class TestDate5 {
public static int compare (GregorianCalendar c1,
GregorianCalendar c2)
{
if ( c1.equals(c2) ) // The equals method.
return 0;
else if ( c1.before(c2) ) // The before method.
return -1;
else
return 1;
}
public static void main (String[] argv)
{
// Create a date.
GregorianCalendar cal = new GregorianCalendar ();
cal.set (Calendar.YEAR, 1998);
cal.set (Calendar.MONTH, Calendar.OCTOBER);
cal.set (Calendar.DAY_OF_MONTH, 5);
Date d = cal.getTime ();
// Create a second date.
GregorianCalendar cal2 = new GregorianCalendar ();
cal2.set (Calendar.YEAR, 1998);
cal2.set (Calendar.MONTH, Calendar.OCTOBER);
cal2.set (Calendar.DAY_OF_MONTH, 5);
Date d2 = cal2.getTime ();
// Compare.
int comp = compare (cal, cal2);
if (comp == 0)
System.out.println (d + " and " + d2 + " are the same");
else if (comp < 0)
System.out.println (d + " comes before " + d2);
else
System.out.println (d + " comes after " + d2);
}
}
GregorianCalendar cal = new GregorianCalendar (
1998, // Year.
Calendar.OCTOBER, // Month.
5 // Day.
);
System.out.println (" DAY_OF_YEAR = "
+ cal.get (Calendar.DAY_OF_YEAR) );
the following gets printed out:
DAY_OF_YEAR = 0
class GCal extends GregorianCalendar {
public void complete ()
{
super.complete ();
}
}
public class TestDate6 {
public static void main (String[] argv)
{
GCal cal = new GCal ();
cal.set (Calendar.YEAR, 1998);
cal.set (Calendar.MONTH, Calendar.OCTOBER);
cal.set (Calendar.DAY_OF_MONTH, 5);
cal.complete();
// Get a Date instance.
Date d = cal.getTime ();
// Print attributes
System.out.println ("Date " + d + " has the following attributes:");
System.out.println (" ERA = "
+ cal.get (Calendar.ERA) );
System.out.println (" WEEK_OF_YEAR = "
+ cal.get (Calendar.WEEK_OF_YEAR) );
System.out.println (" WEEK_OF_MONTH = "
+ cal.get (Calendar.WEEK_OF_MONTH) );
System.out.println (" DAY_OF_YEAR = "
+ cal.get (Calendar.DAY_OF_YEAR) );
System.out.println (" DAY_OF_WEEK = "
+ cal.get (Calendar.DAY_OF_WEEK) );
System.out.println (" DAY_OF_WEEK_IN_MONTH = "
+ cal.get (Calendar.DAY_OF_WEEK_IN_MONTH) );
}
}
This prints out:
ERA = 1 WEEK_OF_YEAR = 40 WEEK_OF_MONTH = 1 DAY_OF_YEAR = 278 DAY_OF_WEEK = 2 DAY_OF_WEEK_IN_MONTH = 1
public boolean isLeapYear (int year);
Using SimpleDateFormat:
Since creating a pattern string can be complicated, let's do this in small steps:
import java.util.*;
import java.text.*;
public class TestDate7 {
public static void main (String[] argv)
{
// Create three patterns.
SimpleDateFormat
sdf1 = new SimpleDateFormat ("yyyy MMMM dd"),
sdf2 = new SimpleDateFormat ("EEEE, MMM dd, yyyy"),
sdf3 = new SimpleDateFormat ("M d HH mm ss");
// try is required: parse can throw an exception.
try {
// In the form "yyyy MMM dd"
Date d1 = sdf1.parse ("1998 October 06");
System.out.println ("Date 1: " + d1);
// In the form "EEEE, MMM dd, yyyy".
// Note the commas.
Date d2 = sdf2.parse ("Tuesday, Oct 06, 1998");
System.out.println ("Date 2: " + d2);
// In the form "M d HH mm ss"
Date d3 = sdf3.parse ("12 25 17 30 11");
System.out.println ("Date 3: " + d3);
// Let's deliberately provide bad input.
Date d4 = sdf1.parse ("October 6, 1998");
System.out.println ("Date 4: " + d4);
}
catch (ParseException e) {
System.out.println (e);
}
}
}
Here's what gets printed out:
Date 1: Tue Oct 06 03:00:00 EDT 1998 Date 2: Tue Oct 06 03:00:00 EDT 1998 Date 3: Fri Dec 25 20:30:11 EST 1970 java.lang.NumberFormatException: Octo at java.lang.Integer.parseInt(Integer.java) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java) at java.text.DateFormat.parse(DateFormat.java) at TestDate7.main(TestDate7.java:27)
The same pattern strings are also used for output:
// Create three patterns.
SimpleDateFormat
sdf1 = new SimpleDateFormat ("yyyy MMMM dd"),
sdf2 = new SimpleDateFormat ("EEEE, MMM dd, yyyy"),
sdf3 = new SimpleDateFormat ("M d HH mm ss");
// try is required: parse can throw an exception.
try {
// Format a date from an string.
Date d1 = sdf1.parse ("1998 October 06");
System.out.println ("Date 1: " + d1);
// Next, we will format the output differently.
String s2 = sdf2.format (d1);
System.out.println (s2);
String s3 = sdf3.format (d1);
System.out.println (s3);
}
catch (ParseException e) {
System.out.println (e);
}
The result is:
Date 1: Tue Oct 06 03:00:00 EDT 1998 Tuesday, Oct 06, 1998 10 6 00 00 00
Now we are in a position to combine these classes:
// Create input and output patterns.
SimpleDateFormat
input_format = new SimpleDateFormat ("yyyy MMMM dd"),
output_format = new SimpleDateFormat ("EEEE, MMM dd, yyyy, HH mm ss");
try {
// Provide a format for input.
Date d1 = input_format.parse ("1998 October 06");
System.out.println ("Date: " + d1);
// Next, wrap a Calendar around a date.
GregorianCalendar cal = (GregorianCalendar) input_format.getCalendar();
// Make changes as desired.
cal.set (Calendar.HOUR_OF_DAY, 17);
cal.set (Calendar.MINUTE, 22);
cal.set (Calendar.SECOND, 35);
// Get back the date.
d1 = cal.getTime();
// Format the output.
String s = output_format.format (d1);
// Print.
System.out.println (s);
}
catch (ParseException e) {
System.out.println (e);
}
Miscellany:
public static final DateFormat getDateTimeInstance ();
// Create a date.
GregorianCalendar cal = new GregorianCalendar (
1998, // Year
GregorianCalendar.OCTOBER, // Month
5, // Day
14, // Hour of day (2 pm)
30, // Minutes
22 // Seconds
);
// Extract the date.
Date d = cal.getTime();
// Use the default format.
DateFormat def = DateFormat.getDateInstance (DateFormat.DEFAULT);
String s = def.format (d);
System.out.println ("DEFAULT: " + s);
// The full format.
DateFormat full = DateFormat.getDateInstance (DateFormat.FULL);
s = full.format (d);
System.out.println ("FULL: " + s);
// The long format.
DateFormat lg = DateFormat.getDateInstance (DateFormat.LONG);
s = lg.format (d);
System.out.println ("LONG: " + s);
// Medium and default are the same.
DateFormat med = DateFormat.getDateInstance (DateFormat.MEDIUM);
s = med.format (d);
System.out.println ("MEDIUM: " + s);
// Short format.
DateFormat sh = DateFormat.getDateInstance (DateFormat.SHORT);
s = sh.format (d);
System.out.println ("SHORT: " + s);
Here's the output:
DEFAULT: 05-Oct-98 FULL: Monday, October 5, 1998 LONG: October 5, 1998 MEDIUM: 05-Oct-98 SHORT: 10/5/98
// Create a date.
GregorianCalendar cal = new GregorianCalendar (
1998, // Year
GregorianCalendar.OCTOBER, // Month
5, // Day
14, // Hour of day (2 pm)
30, // Minutes
22 // Seconds
);
// Extract the date.
Date d = cal.getTime();
DateFormat usa = DateFormat.getDateInstance (DateFormat.FULL,
Locale.US);
String s = usa.format (d);
System.out.println ("USA: " + s);
DateFormat uk = DateFormat.getDateInstance (DateFormat.FULL,
Locale.UK);
s = uk.format (d);
System.out.println ("UK: " + s);
DateFormat france = DateFormat.getDateInstance (DateFormat.FULL,
Locale.FRANCE);
s = france.format (d);
System.out.println ("FRANCE: " + s);
DateFormat germany = DateFormat.getDateInstance (DateFormat.FULL,
Locale.GERMANY);
s = germany.format (d);
System.out.println ("GERMANY: " + s);
This prints out:
USA: Monday, October 5, 1998 UK: Monday, 5 October 1998 FRANCE: lundi, 5 octobre 1998 GERMANY: Montag, 5. Oktober 1998
long start = System.currentTimeMillis ();
for (int i=1; i<=100000; i++) {
int j = i*i;
}
long stop = System.currentTimeMillis ();
System.out.println ("Time taken: " + (stop-start));
In-Class Exercise 8.2:
Use class GCal
above (in this
file) and the
complete()
method to find all years this century in which October 7 falls
on a Wednesday. Print the years in reverse chronological order.
Unlike C/C++, Java's standard output streams do not provide convenient formatting mechanisms.
Without formatting explicitly, output can appear jagged, for example: (source file)
for (int i=0; i<=1000; i+=200) {
int sqr = i * i;
double root = Math.sqrt (i);
System.out.println ("The square of " + i + " is " + sqr +
" and the square root is " + root);
The output is:
The square of 0 is 0 and the square root is 0.0 The square of 200 is 40000 and the square root is 14.142135623730951 The square of 400 is 160000 and the square root is 20.0 The square of 600 is 360000 and the square root is 24.49489742783178 The square of 800 is 640000 and the square root is 28.284271247461902 The square of 1000 is 1000000 and the square root is 31.622776601683793
To format numbers, use DecimalFormat or NumberFormat instances:
First, consider formatting integers:
for (int i=0; i<=1000; i+=200) {
int sqr = i * i;
// Create a DecimalFormat instance, specifying
// width in the constructor.
DecimalFormat df = new DecimalFormat ("00000000");
// Extract a string by passing an int.
String s = df.format (sqr);
// Print the string.
System.out.println (s + " is the square of " + i);
}
The output is:
00000000 is the square of 0 00040000 is the square of 200 00160000 is the square of 400 00360000 is the square of 600 00640000 is the square of 800 01000000 is the square of 1000
Thus, each integer occupies 8 characters, with
leading zeroes filled in.
for (int i=0; i<=1000; i+=200) {
int sqr = i * i;
// Create a DecimalFormat instance, specifying
// width in the constructor.
DecimalFormat df = new DecimalFormat ("########");
// Extract a string by passing an int.
String s = df.format (sqr);
// Print the string.
System.out.println (s + " is the square of " + i);
The output is:
0 is the square of 0 40000 is the square of 200 160000 is the square of 400 360000 is the square of 600 640000 is the square of 800 1000000 is the square of 1000
Note: using the #-symbol
does not achieve fixed-width formatting.
0 is the square of 0 40000 is the square of 200 160000 is the square of 400 360000 is the square of 600 640000 is the square of 800 1000000 is the square of 1000
we need to pad blanks.
DecimalFormat df = new DecimalFormat ("#");
is equivalent to:
DecimalFormat df = new DecimalFormat ("########");
Next, consider formatting double's:
double d1 = 9876.543;
double d2 = 9876.0;
double d3 = 0.543;
DecimalFormat df = new DecimalFormat ("#.#");
String s1 = df.format (d1);
String s2 = df.format (d2);
String s3 = df.format (d3);
System.out.println ("d1=" + s1 + " d2=" + s2 + " d3=" + s3);
// Prints "d1=9876.5 d2=9876 d3=.5"
df = new DecimalFormat ("####.####");
s1 = df.format (d1);
s2 = df.format (d2);
s3 = df.format (d3);
System.out.println ("d1=" + s1 + " d2=" + s2 + " d3=" + s3);
// Prints "d1=9876.543 d2=9876 d3=.543"
df = new DecimalFormat ("0.0");
s1 = df.format (d1);
s2 = df.format (d2);
s3 = df.format (d3);
System.out.println ("d1=" + s1 + " d2=" + s2 + " d3=" + s3);
// Prints "d1=9876.5 d2=9876.0 d3=0.5"
df = new DecimalFormat ("0000.0000");
s1 = df.format (d1);
s2 = df.format (d2);
s3 = df.format (d3);
System.out.println ("d1=" + s1 + " d2=" + s2 + " d3=" + s3);
// Prints "d1=9876.5430 d2=9876.0000 d3=0000.5430"
Finally, noting how complicated it is to use DecimalFormat, we provide some simple methods to specify precision: (source file)
class EasyFormat {
// Pad blanks as required (for both int's and double's).
static String pad_blanks (String s, int target_len, boolean is_int)
{
int slen = s.length();
// No decimal point to worry about with int's.
if (is_int) {
if (slen >= target_len)
return s;
// Otherwise we pad from front
for (int i=1; i <= target_len-slen; i++)
s = ' ' + s;
return s;
}
// Otherwise check up to decimal point
int i = s.indexOf ('.');
if ((i < 0) || (i >= slen)) {
System.out.println ("ERR: pad_blanks: no decimal point");
System.exit(1);
}
if (i+1 >= target_len)
return s;
// Otherwise, pad with blanks
for (int j=1; j < =target_len-(i+1); j++)
s = ' ' + s;
return s;
}
// Format integers.
public static String format (long i, int width)
{
DecimalFormat df_i = new DecimalFormat ("#");
String s_i = df_i.format (i);
s_i = pad_blanks (s_i, width, true);
return s_i;
}
// Format double's.
public static String format (double d, int before_dec_pt,
int after_dec_pt)
{
// Use '#' symbols before decimal point.
String s = "";
for (int i=1; i < before_dec_pt; i++)
s = s + '#';
// Force a zero for numbers less than 1.0
s = s + "0.";
// Include zeroes as specified by width.
for (int i=1; i < =after_dec_pt; i++)
s = s + '0';
DecimalFormat df_d = new DecimalFormat (s);
String s_d = df_d.format (d);
// Pad blanks.
s_d = pad_blanks (s_d, before_dec_pt, false);
return s_d;
}
}
public class TestNumber4 {
public static void main (String[] argv)
{
for (int i=0; i<=1000; i+=200) {
String s = EasyFormat.format (i, 4);
int sqr = i * i;
String sqr_string = EasyFormat.format (sqr, 8);
double root = Math.sqrt (i);
String root_string = EasyFormat.format (root, 5, 3);
System.out.println ("The square of " + s + " is " + sqr_string +
" and the square root is " + root_string);
}
}
}
The output is:
The square of 0 is 0 and the square root is 0.000 The square of 200 is 40000 and the square root is 14.142 The square of 400 is 160000 and the square root is 20.000 The square of 600 is 360000 and the square root is 24.494 The square of 800 is 640000 and the square root is 28.284 The square of 1000 is 1000000 and the square root is 31.622
These useful methods have been included in the New_io class described earlier.
One of the methods in class java.lang.Object is the following:
public class Object {
// ...
public final native Class getClass();
// ...
}
Notice that the return value is something called Class (capital C).
What is this thing called Class?
public final class Class implements Serializable {
// Class methods:
public static native Class forName (String name)
throws ClassNotFoundException;
// Some instance methods:
public native String getName ();
public Constructor[] getConstructors ()
throws SecurityException;
public Field[] getFields ()
throws SecurityException;
public Method[] getMethods ()
throws SecurityException;
}
What it it used for?
Obj_A a = new Obj_A (); Class c = a.getClass (); // getClass() is inherited from Object.
A simple example:
String s = "hello"; // A String is a class. Class c = s.getClass (); // Get info about String's. System.out.println (c); // Print.
This is the output:
class java.lang.String
In this case, the name of the class (java.lang.String) is printed out.
Now suppose we define Obj_A as:
class Obj_A {
// Data.
int n;
double x;
// Constructors.
public Obj_A (int n, double x)
{
this.n = n; this.x = x;
}
public Obj_A ()
{
this (0, 0);
}
// Methods.
public static void print ()
{
System.out.println ("Obj_A");
}
public String toString ()
{
return "Obj_A: n=" + n + ", x=" + x;
}
}
Suppose now we want to extract information about the definition of Obj_A given an instance. Here's how:
Obj_A a = new Obj_A (); c = a.getClass (); System.out.println (c);
Instead of only getting the name, we can actually find out everything about Obj_A.
For example, we can count the constructors of Obj_A:
// Get constructors of Obj_A.
Constructor[] ctor = c.getConstructors ();
System.out.println ("Obj_A has " + ctor.length + " constructors");
or print a list of its methods:
// Get methods of Obj_A.
Method[] method = c.getMethods();
System.out.println ("Obj_A has " + method.length + " methods: ");
for (int i=0; i < method.length; i++) {
String name = method[i].getName();
System.out.println (" " + name);
}
Note:
public final class Method implements Member {
// Member is an interface in java.lang.reflect.
// Some instance methods:
public Class getDeclaringClass(); // Get name of class.
public String getName(); // Get method name.
public Class[] getParameterTypes(); // Get list of parameter types.
public Class getReturnType(); // Get return value type.
// A very useful method - for dynamic invocation.
public native Object invoke (Object obj, Object[] params)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException;
}
You can go a step further: given just the name of a class, you can create an instance and use it: (source file
import java.lang.reflect.*;
class Obj_A {
// Data.
int n;
double x;
// Constructors.
public Obj_A (int n, double x)
{
this.n = n; this.x = x;
}
public Obj_A ()
{
this (0, 0);
}
// Methods.
public static void print ()
{
System.out.println ("Obj_A");
}
public String toString ()
{
return "Obj_A: n=" + n + ", x=" + x;
}
}
public class TestClass {
public static void call_toString (String obj_name)
{
try {
// Get the Class instance first.
Class c = Class.forName (obj_name);
// Get a list of methods.
Method[] method = c.getMethods();
// Go through and look for toString()
for (int i=0; i < method.length; i++) {
// Get name of i-th method.
String name = method[i].getName();
// If it is toString ...
if (name.equals ("toString")) {
System.out.println (obj_name + " has a toString() method");
try {
// Create an instance of the object on the fly.
Object instance = c.newInstance ();
// No parameters, so a size=0 array is passed.
Object[] obj_array = new Object[0];
// Call the powerful invoke() method.
// Note: toString returns a string.
String output = (String) method[i].invoke (instance, obj_array);
// Print out the string returned from toString()
System.out.println ("String returned: " + output);
}
// Catch a whole bunch of exceptions.
catch (InstantiationException e) {
System.out.println (e);
}
catch (IllegalAccessException e) {
System.out.println (e);
}
catch (InvocationTargetException e) {
System.out.println (e);
}
}
}
}
catch (ClassNotFoundException e) {
System.out.println (e);
}
}
public static void main (String[] argv)
{
call_toString ("Obj_A");
}
}
Since Obj_A has a toString(), it gets called and here's what is printed out:
Obj_A has a toString() method String returned: Obj_A: n=0, x=0.0
Thus, the class Class and the classes in java.lang.reflect can be used to dynamically create instances of any class.