Inheritance &
Constructors,
Vector & java.lang Classes
Peter
Komisar © Conestoga College latest version 5.6
/ 2010
This class
follows off of last week's discussion of Inheritance, this
time bringing attention to details of overriding and overloading
constructors. It goes on to survey Java's built in lang package
classes.
In
object-oriented programming, data and operations are
formally coupled
in the data structure called the
'class'.
The class acts as a container for it's members.
Class
members include 'fields',
which are also called 'variables'.
Variables hold values that describe characteristics or
properties of an object. The class member that describes
behavior
is the 'method'.
Methods have
counterparts in other languages known as
functions, procedures,
routines or operations. Methods
are the verbs
or action parts of a class.
Java classes also hold
'constructors'. These are special
methods whose sole job is to create what are called new
instances
or objects of a given class. This study covers
aspects of constructors that are tied to inheritance.
Class members
Constructors & Overloading
Review: Invoking a
Constructor
A
constructor is a unique and privileged method which is
used to create and initialize new objects. Creating
a class
instance using the constructor with the new operator
is
called instantiation. In the following example, declaration,
instantiation and assignment are all combined.
Example
AClass
reference = new AClass( );
// a
constructor being invoked
The above example shows
a constructor being deployed
in the instantiation process.
Defining a
Constructor
When
defining a constructor in a class definition the
constructor has
three distinguishing elements. A
constructor:
The implied return type
of the constructor is the class
object that is set up in memory.
Constructors are like
methods in that they use of round braces to
receive
arguments and the use of curly braces to define the
scope
of their actions. Following is the general form
of the
constructor.
General Form of a Constructor inside a Class Definition
class Name{
Name(
){
// the constructor with
same name as class,
// no return type and round
braces
}
}
First consider a class
called Car defined without any
constructors defined.
Example
class Car{
// variables
int speed = 7;
int braking = 7;
int handling = 7;
// method
int getRating( ) { return speed + braking + handling; }
}
Now lets look at a
Car class and define a constructor
in it. First notice the
constructor has the same name
as the class, Car, and has no
return type, unlike it's
sibling, the method.
class Car{
//
variables defined in class scope initialized to the default value 0
int speed;
int braking;
int handling;
// an no-args constructor
Car(
){
speed =7;
braking= 7;
handling = 7;
}
// class method
int
getRating(
) { return speed + braking + handling; }
}
The
no-args Default Constructor
If we test the above
classes we see they work the same.
You might ask what was accomplished using the form
with the constructor. Beyond being perhaps of better form,
nothing!
This is because, in the
absence of a constructor being
supplied explicitly, a
'no-argument' default constructor
is supplied implicitly by the Java
compiler. This supplied
constructor does the same work of initialization
that the
explicitly defined constructor does.
//
in the absence of an overtly supplied constructor
// the default no-args
constructor is supplied
Constructor Non-Participation In Inheritance
We have seen that
inheritance allows a
class to extend
another class in such a way as to have access to
the
members of the parent class. We are able to assign
values
to the parent variables as if they had been
defined in the child
class.
Constructors, on the other
hand, are not
really considered
to be class members though they are ostensibly
defined
within the class definition. This follows from the fact
that
they are used to create class objects rather than being
a
participating member of the class object.
// constructors are not true class
members as they cannot
// participate in an object's operations
There is a special case
that pertains to this discussion. If
you define a class with a
constructor that takes arguments
then the compiler doesn't supply the no-args default
constructor automatically. The following code doesn't compile
for this reason.
Example
class Construct{
Construct(String s){
System.out.println(s);
}
public static void main(String[] args){
new Construct( );
//
doesn't compile as the no-args constructor is not
// provided in the case that any constructors are
defined
}
}
OUTPUT
>javac
Construct.java
Construct.java:7: cannot find symbol
symbol : constructor Construct()
location: class Construct
new Construct( );
^
1 error
If a child class is built
that attempts to invoke the no-args
constructor of the parent, the compile will fail as that version
of the constructor
in the parent is not defined. The solution
here is to provide a no-args constructor
explicitly whenever
you decide to define constructors for a class.
This is shown in the next
example which may be saved as
'Run.java', the class that contains the main( ) method.
//
The no-args constructor is supplied automatically only
// if other constructors are not explicitly defined in a class.
Constructor Code Sample
class Parent
{
// if you
comment out the no-args constructor you will
// get a compiler error as the compiler has not supplied
// the no-args constructor for the child to invoke
//
a
no args constructor, to comment in and out
//
and
a constructor that takes a String object
// /*
Parent( )
{
System.out.println
("The no-args
parent constructor is expressed");
}
//
*/
Parent(String name)
{
System.out.println
("Hello " + name + "! A
constructor that takes a String is expressed.");
}
}
// child
class
class Child
extends Parent
{
Child( ){
System.out.println
("This is
followed by the child's constructor being invoked.");
}
}
class Run
{
public static void main(String[]args)
{
new Child( );
}
}
OUTPUT // without the no-args constructor defined in parent
C:\Documents and
Settings\Peter\My Documents\J2\Examples>javac Run.java
Run.java:29: cannot find symbol
symbol : constructor Parent()
location: class Parent
Child( ){
^
1 error
Constructor
Overloading
Recall
from
tours
of the documentation that more than one
constructor can be supplied for a
class. In the following
example we can build the Car class with
three constructors.
We are defining the
class without variables and methods to
simplify the
view.
Example
class Car{
Car( ) {
// the no args constructor
supplied
explicitly
}
Car(String
options){
// a constructor defined taking a
String argument
}
Car(String
options,
String customization){
// a constructor defined taking two
string arguments
}
The compiler doesn't
mind several constructors being built
with the same name. This
is called constructor overloading.
This is similar to method
overloading where the compiler is
able to
distinguish each constructor based on the order,
type and number
of arguments.
Recall
that the keyword 'this' could be used to reference
variables or method defined in the scope
of
a container
class, that is, the
class that contains those variables and
methods. The 'this' keyword
also has a special form that
is used to reference
constructors defined inside a class.
In
the case of constructors, the 'this'
keyword is used
as an identifier
together with the form of
the constructor
that it is being
used to invoke. For instance the following
example shows how
to invoke a constructor in the current
class that has an argument list consisting of a String,
and an int value. (Another way of
to
say this is that the
form matches a constructor defined in the
current class
with a matching
constructor signature.)
Example
this( "x", 9 );
//
invokes a constructor in the current class
// that takes a String value
and an int
This
is demonstrated in code in the following example.
Example
class Limo{
Limo(String stretch, int spec1, int spec2, int spec3){
// some complex processing
}
Limo(String stretch, String tinted ){
this(stretch , 1, 2, 3 );
//
go on to use the added argument
// calls the
adjacent constructor with matching argument list
//
then do further construction, using tinted directive
}
}
Where
the
'this'
keyword used with constructors references
constructors
defined in the containing class, the 'super'
keyword can be used in constructors
to reference a target
constructor defined in a parent class.
The
super keyword is used in a similar way that the 'this'
keyword, in a form that imitates a
constructor that needs
to be invoked. The difference is the 'super'
keyword is
used to
invoke a matching constructor in the
parent class.
To
example this we need to create a
constructor where a
child class subclasses a
parent. First we define Car class
with two constructors.
class Car{
Car(String
options){
// build car with
standard options
}
Car(String
options,
String customization){
// build car with custom options
}
//
potential problem as the no-args
//
good
practice to start with a no-args
//
constructor
or supply an empty one
}
Now we create a
SportsCar class that extends the parent
class, Car. Notice how we
use 'super' to specifically invoke
one of the parent constructors by
matching the argument
lists.
Example
class SportsCar extends Car{
SportsCar(String
options ){
super(options);
// passes control to the parent
// constructor with matching signature
}
}
Notice
now
if
we tried to use the no-args super( ) we would
get a compiler
error because now that constructors
have
been defined in the Car class the no-args constructor
has
not been supplied.
The 'this' and
'super' Keywords Both Want to Be First
A
final point on 'this' and 'super'. If the constructor form
of these
keywords are used, Java programming rules
state that each must be the
first statement in the
constructor code block. This leads to the
obvious,
conundrum, 'In a constructor that uses both, how can
they both be
first? Both insist on being
the first call
in a constructor.
Example // won't compile
class
P
{
P( ) {
}
}
class C{
C( ){
// putting either
this( ) or super( ) before the other won't compile
super( );
this( );
}
public static void main(String[]args){
new C( );
}
}
To
use use both, one must do so in stages by first
defining a constructor that uses super and then build
a constructor that invokes that constructor using this.
Following
is another complete example showing super
and this used inside
constructors
Second
Constructor Example
class
Old{
Old( ){
System.out.println("No-args Old");
}
Old(String name){
System.out.println("Hi " + name + "! I am Old's one
arg constructor being invoked.");
}
}
class Young extends
Old{
Young(String name){
super(name);
System.out.println("Young having called String constructor of
Old");
}
Young(String name, String day, String month){
this(name);
System.out.println("Young calls 'this' and adds it's own
properties");
System.out.println(" Day is: " + day + " and " +
" Month is: " + month + "\n");
}
}
public class OY{
public static void main(String[] args){
System.out.println( " \n**** No arg Old ****\n " );
new Old();
System.out.println(
" \n**** Single arg Young ****\n " );
new Young("Bentley");
System.out.println( " \n**** One arg Old ****\n " );
new Old("Syvester");
System.out.println( " \n**** Three args Young ****\n "
);
new
Young("Melissa","Thursday","April");
}
}
OUTPUT
**** No arg Old **** No-args Old **** Single arg Young **** Hi Bentley! I am Old's one arg constructor being invoked. Young having called String constructor of Old **** One arg Old **** Hi Syvester! I am Old's one arg constructor being invoked. **** Three args Young **** Hi Melissa! I am Old's one arg constructor being invoked. Young having called String constructor of Old Young calls 'this' and adds it's own properties Day is: Thursday and Month is: April |
The following
code sample demonstrates the invocation
of parent and grandparent
constructors. Notice how the
constructors are invoked recursively up the inheritence
chain. This invocation happens by implicit calls to super( )
all the way back to Object class.
Sample
Demonstrating
Invocation
of Ancestor Constructors
class
Dark{
Dark(){
System.out.println("1. Dark");
}
public static void main(String[] args){
new Dark();
new Dawn();
new Day();
}
}
class Dawn extends Dark{
Dawn(){
System.out.println("2. Dawn");
}
}
class Day extends Dawn{
Day(){
System.out.println("3.
Day");
}
}
Output
1.
Dark
1. Dark
2. Dawn
1. Dark
2. Dawn
3. Day
The
redundancy in the output demonstrates how parent
constructors are
invoked recursively.
Garbage Collector
Replaces C++'s Destructors
A
last word about Java constructors, if
this was a C++ course
we would go onto a discussion of
destructors, the counterpart
of a
constructor. Java saves us the need to deallocate memory
by providing the 'gc' thread where 'gc'
abbreviates garbage
collector.
The 'gc' thread is a
daemon
or service thread that works in the
background taking advantage of slow times in CPU usage
deallocating memory locations that are no longer referenced.
Classes of the java.lang Package
The
Java library of classes is enormous and growing! Java has
a set of 'built-in' classes
that are automatically imported for the
programmer that do basic 'bread and butter' activities.
These
classes provide support that is so fundamental that they are
supplied automatically. These classes are found
in the
java.lang package.
Primary
classes
in
this package are the
String class and the
Math
class. There is also the set of Wrapper classes, one for
each
primitive type.
There
are
other
neccessary classes like System, class
Class
and ClassLoader. Object class
is defined in the lang package
as is the Thread class. Java's
SecurityManager is also defined
in the java.lang
package.
The
lang package is also where two
dozen Exception classes
and twenty-one error classes are defined. In this section we look
at the
String, Math and Wrapper classes.
Common Classes Found In the java.lang
Package
Vector in the java.util Package
Though
in
a
different package, the util package, Vector is
included
too, because it has been used so much throughout the Java libraries.
Though Vector
is
often
replaced by classes such as ArrayList,
contained in the collection
package, it remains a classic Java
workhorse.
//
ArrayList adds some nice features however ArrayLists operations are not
// synchronized as are
Vector's
methods. In a
multi-threaded environment,
// you would need to make sure calls
on
ArrayList
are synchronized.
The String Class
In Java when you
need a string of characters in your programs,
you use an instance of
the String class. String objects hold a
series of adjacent
characters in a way similar to an array.
However, where with an array
you would reference an element
of the array to get a character,
with String you use one of the
class methods to manipulate the
string.
String Literals
A String literal is
created when zero or more characters are
enclosed in double quotes.
Example
"A String literal" // String literal
String literals are
normally used in some context. For instance
as an argument to a
method.
Example
setText(" String literal as a method argument " );
String literals are
also used in assignments.
Example
String string;
string = "A
String literal assigned to a reference variable";
String is a class so
an object of String class can also
be created using a String class
constructor.
Example
String s = new String("A
string" );
Strings as Immutable Objects
Strings are said to be
immutable.
This means a
String
object is unchangeable. This description makes it sound
as though a String object is somehow
final like a variable
that has been marked final and can no
longer be changed.
What is actually unchangeable is the String object that
has
been stored in memory.
So how do we make changes
to a
String object? What
occurs when Java methods are used to change a String
object is that the string is copied
into an instance of the
mutable StringBuffer class. StringBuffer has a memory
area that can be used to modify and rearrange strings.
Changes
are made to the StringBuffer representation and
then a new immutable String
object is built in memory.
The old reference is then reassigned the
new object while
the old dereferenced object is discarded.
Once no
longer referenced, it is a matter of time before
the
background gc thread deallocates the
object and the
memory once associated with the old immutable String
object is freed.
//
When a change on a string is executed the string is written to a
// StringBuffer the modifications
are effected and then a new immutable
// String object is
created.The reference to
the string object is made to
// point to the new string object in memory and and the old object in
// memory is dicarded
The
Overloaded Addition Operator
There is one case of
operator overloading in Java. The
addition operator, represented by the '+' symbol, is
overloaded
to do String concatenation. (Overloading in
this context is
when a symbol is able to do more than
one kind of operation in a
language.) If one of the operands
to the operator, +
is a String object, the other type will
either be promoted
to String type (as in the case of
primitives) or the toString( )
method will be called on it
(in the case of object types.) In the
following case each
primitive value represented by x and y will be
supplied
in their String form.
Example
System.out.println(" x is " + x + "y is " + y );
Common
String class Construction
Following
are
two
common constructions of a String
object. The first uses a
constructor while the second
is a
String literal assignment.
Example1
String s1 = new String(
"common
constructor");
// via a constructor
Example
2
String
s2 = "a string
literal";
// assigning a string literal
There are several String
constructors ( 9 ) and String
objects can be created in a number of
ways. The following
example shows a String object constructed from an
array
of char type.
Example
String ball = "balloon"; // is equivalent to:
char
parts[] = {'b', 'a', 'l','l','o','o','n'};
String
ball2 = new String(parts);
Deep and Shallow Comparisons
When reference types
are compared via the equality
operator, ==, the addresses stored in
the references are
compared. This is called a shallow
comparison. If the
equals( ) method is used, the
contents pointed to by the
address stored in the reference is
compared. This is a
deep comparison.
The following two cases cover the
different unique circumstances
that may occur.
Comparisons of Same Addresses & Same Stored Values
To complicate matters,
the Java environment maintains
'a pool of
string literals'.
Each string literal is represented
in
the pool. Identical string literals are only represented
once in the
pool of literals during a
Java program's run.
//
the string literal pools complicates matters
If
an identical literal is
used twice in a program, it is only
represented once in the literal
pool. When deep and shallow
comparison are made on the two references representing
the same
string literal value the result is
consistent with
this fact. The addresses will be the same and the deep
comparison of value will also be the same.
Example
String
xx
=
"X";
String xy = "X";
if
(xx.equals(xy))
//
a 'deep' comparison ( of values stored ) resolves to true
// . . .
if
(xx = =
xy)
// a 'shallow' comparison for these references also
resolves to true
The
second "shallow" comparison also resolves to true
as the
addresses where the string literal, "X" is stored,
is
the same location.
Comparisons
of Different Addresses but Same Values
On
the other hand, when a reference is created via a
constructor
that points to a String literal, first the literal
is recorded in the literal pool and then a new string is
created in memory, copied from the one in the
literal
pool. This copy is stored at a different location and so,
will not share
the same address as the one in the
literal
pool.
Example
2
String yy = "X";
String yx = new String("X");
if
(yy.equals(yx))
// a 'deep' comparison (of stored values) resolves to true
//
however the shallow comparison resolves to false
if (yy = =
yx)
Code Sample Demonstating Deep and Shallow Comparison
class sTz{
public static void main(String[] args){
// First Scenario
String xx = "X";
String xy =
"X";
if
(xx.equals(xy))
System.out.println
("\n"+"A deep comparison tests true for comparison on
literal assignmnents");
if (xx ==
xy)
System.out.println
("A shallow test yields true indicating one value is stored at
one address \n");
// Second
Scenario
String yy = "X";
String yx =
new String("X");
if
(yy.equals(yx))
System.out.println
("Values are the same when assigned by literal or by
literal-supplied constructor");
if (yy == yx)
;
else
System.out.println
("Shallow
tests false showing the two values are stored at different
addresses");
}
}
OUTPUT
> java
sTz
A deep comparison tests true for comparison on literal assignmnents
A shallow test yields true indicating one value is stored at one address
Values are the same when assigned by literal or by literal-supplied
constructor
Shallow tests false showing the two values are stored at different
addresses
Following is a summary of the String class constructors and methods.
This lift is from an older JDK and more may have been
added by now.
This is provided to overview String class capabilities.
Constructor
Summary
Here
are 9 String constructors that show String instances can be created
from an empty character sequence, a
provided String object (where in fact
a copy is created and
encapsulated in the new instance), a StringBuffer
instance, and
arrays. (or parts of arrays), of
byte and char type, with or
without specified character encodings.
String( ) |
Initializes a newly
created String object so |
String(byte[] bytes) |
converts array of bytes using the
platform's |
String(byte[]
bytes, |
convert specified
subarray of bytes
using the |
String(byte[]
bytes, int offset, |
convert the
specified subarray of
bytes
using
|
String(byte[] bytes,
|
converts the
specified array of
bytes using |
String(char[] value) |
creates a new
String representing the character |
String(char[] value,
|
creates a new
String representing the character |
String(String value) |
Initializes a newly
created String object that |
String(StringBuffer buffer) |
creates a new
String based on the character |
// constructors deprecated because they didn't work properly are left out
Method
Summary
// the short
summary from the JDK API documentation
char charAt(int index) |
Returns the
character at the specified index. |
int compareTo(Object o) |
Compares this String to another Object. |
int compareTo(String StringB ) |
Compares two
strings lexicographically. |
int
compareToIgnoreCase |
Compares two strings
lexicographically, |
String concat(String str) |
Concatenates the
specified string to the end |
static String
copyValueOf |
Returns a String
equivalent to the given |
static String copyValueOf
|
Returns a String
equivalent to the given |
boolean endsWith(String suffix) |
Tests if this string ends with the specified suffix. |
boolean equals(Object anObject) |
Compares this string to the specified object. |
boolean equalsIgnoreCase
|
Compares this
String to another String, ignoring |
byte[] getBytes( ) |
Converts String to
bytes according to the |
byte[] getBytes(String enc) |
convert String to bytes
according to the |
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) |
Copies characters from
this string into the |
int hashCode( ) |
Returns a hashcode for this string. |
int indexOf(int ch) |
Returns the index within
this string of the |
int indexOf(int ch, int fromIndex) |
Returns the index within
this string of the first occurrence of the specified character,
starting |
int indexOf(String str) |
Returns the index
within this string of the |
int indexOf
|
Returns the index within
this string of the first occurrence of the specified substring,
starting |
String intern( ) |
Returns a canonical
representation for the |
int lastIndexOf(int ch) |
Returns the index within
this string of the |
int lastIndexOf
|
Returns the index within
this string of the |
int lastIndexOf(String str) |
Returns the index within
this string of the |
int lastIndexOf
|
Returns the index within this string of the last occurrence of the specified substring. |
int length( ) |
Returns the length of this string. |
boolean
regionMatches (boolean |
Tests if two string regions are equal. |
boolean regionMatches(int
toffset, |
Tests if two string regions are equal. |
String replace
|
Returns the string that
result from replacing |
boolean startsWith(String prefix) |
Tests if this string starts with the specified prefix. |
boolean startsWith
|
Tests if this string starts with the specified prefix beginning a specified index. |
String substring(int beginIndex) |
Returns a new string that
is a substring of |
String substring
|
Returns a new
string that is a substring of |
char[] toCharArray() |
Converts this string to a new character array. |
String toLowerCase( ) |
Converts all of the
characters in this String |
String toLowerCase
|
Converts all of the
characters in this String to |
String toString() |
This object (which is already a string!) is itself returned. |
String toUpperCase() |
Converts all of the
characters in this String to |
String toUpperCase(Locale locale) |
Converts all of the characters in this String to upper case using the rules of the given locale. |
String trim() |
Removes white space from both ends of this string. |
static String valueOf(boolean b) |
Returns the string
representation of the |
static String valueOf(char c) |
Returns the string representation of the char argument. |
static String valueOf(char[] data) |
Returns the string representation of the char array argument. |
static String
valueOf |
Returns the string representation of a specific subarray of the char array argument. |
static String valueOf(double d) |
Returns the string
representation of the |
static String valueOf(float f) |
Returns the string representation of the float argument. |
static String valueOf(int i) |
Returns the string representation of the int argument. |
static String valueOf(long l) |
Returns the string representation of the long argument. |
static String valueOf(Object obj) |
Returns the string
representation of the |
String
Class
Code
Example
The following code
example shows that the methods of
the String class are pretty
straight forward to use.
import java.io.*;
class
StringT{
public static void main(String[]
args){
char[] sa = {'S', 'a', 't', 'u', 'r','n'};
String string = new
String(sa);
// one of String's constructors
System.out.println("\n 1. string has the
value " +string );
String sb = " Rings"; // added a space!
int i
=
string.compareTo(sb);
// compareTo( )
System.out.println(" 2. The lexigraphical comparison yields "
+ i );
String
cat=string.concat(sb);
// concat( );
System.out.println(" 3. sb concatenated to string is: " +
cat + "\n");
try{
byte[] b= new byte[string.length( )];
System.out.println(" 4. string length is
" +string.length( )+"\n");
for(int k=0;k<b.length;k++){
b = string.getBytes("8859_1");
//
getBytes("8859_1") with character encoding
System.out.println(b[k]);
}
}
catch(UnsupportedEncodingException uee){
//
have to catch unsupported encoding
System.out.println("Unsupported Encoding");
}
int j =
string.indexOf("St");
// indexOf( )
System.out.println("\n 5. The first occurence
of ring is at index " + j );
// This reports index 0 so
think of the index like an offset starting
at zero
int z =
(int)'T';
// casting a char type to an int
System.out.println(" 6. The char literal T cast
to an int is "+ z);
System.out.println("
7.
before
and
after
trim()
\n");
// trim( )
System.out.println("
before length: " + " xyz
".length());
// calling on string
literals
System.out.println("
after length: " + " xyz
".trim().length());
String
string2=string.valueOf(sa);
// valueOf used on a char array
System.out.println("\n 8. This is sa array
returned as a string " + string2);
}
}
OUTPUT
> java
StringT
1. string has the value Saturn
2. The lexigraphical comparison yields 51
3. sb concatenated to string is Saturn Rings
4. string length is 6
83
97
116
117
114
110
5. The first occurence of ring is at index -1
6. The char literal T cast to an int is 84
7. before and after trim()
before length: 9
after length: 3
8. This is sa array returned as a string Saturn
Wrapper Classes
Sometime you will
need to treat a primitive type, such as an int
or boolean type as an object. For example, a primitive type cannot
be added directly to a Vector. Often
though, number data would
need to
be added to a Vector. Vector can only receive Object
types.
Wrapper
classes
serve in this role, to encapsulate primitive types
in class objects
so they can be treated like object types. For instance,
Integer
is the wrapper class for integers. A wrapper class exists for
each of the primitive types.
The Wrapper class name
for each primitive can be deduced by
starting the unabbreviated
version of the primitive type name with
capitals. For example, int type's wrapper class is the
Integer class,
while the char type's wrapper is the Character
class. All the primitives
and their corresponding wrapper classes are
listed in the following
table.
Wrapper
Class for each Primitive Type
Wrapper |
Primitive |
Boolean |
boolean |
Character |
char |
Byte |
byte |
Short |
short |
Integer |
int |
Long |
long |
Float |
float |
Double |
double |
Besides providing
objects types for primitives, wrapper classes
store useful constants
and methods to convert to and from String
and other types. In the following example one of the
important roles
wrapper classes serve is shown.
Wrapper Classes Represent Immutable Values Like the String Class
Another important point
about the wrapper classes, they are like
the String class and
represent immutable values. There is a similarity
between the
wrapper classes and the String class in that the String
class
represents a wrapper for a collection of primitive 'char' type and
the
wrapper classes serve as containers for the other numerical
primitive types.
Wrappers Have Important Type Conversion Methods
The
Integer wrapper class static
parseInt( ) method converts a
String value to an int value. In fact each of the wrappers has an
equivalent method. This is important as numbers are often provided
as String type and need to be converted.
In
the case of the Integer wrapper
class, the object is built
by passing
an int value as an argument to the Integer class
constructor.
Example
Integer
integer
= new Integer(2012);
Object classes
toString( ) method can be implicitly invoked
to render a String version of the object.
Example
public
class _2012{
static
Integer integer = new Integer(2012);
public
static void main(String[]args){
System.out.println(integer);
}
}
Following
is some code that examples some of the
methods
that the wrapper classes offer. A String value is received
from the command line and converted to an int by the
static parseInt( ) method of the Integer class. This int
is wrapped in it's own Integer wrapper class. A conversion
method is called on this object and the initial value is
returned as a float. We don't have to
catch the runtime
NumberFormatException but nothing stops us from doing
so.
Wrapper
Class Code Example
/* parseInt() is a static method called here on the class * name */
class
Wrap{
public
static void main(String[] args){
if(args.length
< 1){
System.out.println("Enter
a number at the command line");
System.exit(0);
}
try{
int
i=Integer.parseInt(args[0]);
Integer
theWrapperClass= new Integer(i);
float
f = theWrapperClass.floatValue( );
//
intValue( ) returns enclosed wrappers int value
System.out.println("Here's
your number as a float: " + f);
}
catch(NumberFormatException
nfe){
System.out.println("Your
number is too big or has a format problem");
System.exit(0);
}
}
}
//
The number output converts to exponential floating point
// form at 10
million. A
NumberFormatException is thrown
// when the range of an
int is exceeded,~ +/- 2.147
billion.
The Math Class
Math
contains a collection of mathematical methods and
two constants. The
constants are Math.PI and Math.E.
Both are public, static, final and double. The Math class
itself is made final so cannot be
sub-classed. It's
constructor is private so it cannot be
instantiated. It's
methods and constants are
static so can be accessed
through the class
name. This results in a rigid class
definition, with tight security controls.
The
way the Math class has been created makes it
very easy to use. Static method invocations are made
on the class name.
Example Math.random( );
A
Brief look at Math class Methods
abs(
)
There are four versions of
abs( ), each which returns an
absolute value for a value
provided which may be int, long,
float, or
double.
// resolves a -2 to a 2
ceil(
) & floor( )
These
methods take and return doubles corresponding to
the nearest int
value above or below the double
provided
// ceil( ) will resolve a 1.1
to a 2
max(
) & min( )
There are
four versions of each max( ) and min( ) for int,
long, float and
double types. These methods take two
values and return the greater or the lesser of two,
respectively.
random(
)
random( ) returns a random
number between 0.0 and just
less than 1.0. This method acts
as a wrapper for the
creation of an instance of the Random class
which is
one of the utility methods
supplied in the java.util package.
// Random # formula: random number = (int)( Math.random(
)*number_range) + 1
round(
)
Two forms of this method are
available to round a float (to
an int) or a double (to a long)
sin(
), cos( ) & tan( ) // there are also
asin acos atan & atan2
These
methods take doubles and return the sine, cosine,
and tangent as
doubles.
sqrt(
double d )
sqrt( )
returns the square root of a double provided as an
argument
pow(double
number, double power)
pow( )
returns a number evaluated to a given power
log(
)
Returns the natural logarithm
(base e) of a double value.
exp(
)
Returns the exponential number
e (i.e., 2.718...) raised to
the power of a double value.
rint(
)
takes a double, rounds to an
int then returns this value
as a double
IEEEremainder(double
f1, double f2 )
returns an IEEE
formulated remainder of a division
//
supplemental information The remainder value is mathematically
// equal
to f1 - f2 × n, where n is
the mathematical integer closest
// to the exact mathematical value of
the quotient f1/f2, and if two
// mathematical integers are equally close to f1/f2, then n is the
// integer that is even.)
toDegrees(
) // new
since
JDK1.2
Converts an angle
measured in radians to the equivalent
angle measured in degrees.
toRadians(
) //
new since JDK1.2
Converts
an angle measured in degrees to the equivalent
angle measured in
radians.
// these methods may through a runtime
NumberFormatException
// Try entering something like
5y5 and see the error report
Math Code Example
class
MathMethods{
public static void main(String[] args){
if(args.length <6){
System.out.println("Enter
6
numbers at the command line");
System.exit(0);
}
int
a=Integer.parseInt(args[0]);
int b=Integer.parseInt(args[1]);
int c=Integer.parseInt(args[2]);
int d=Integer.parseInt(args[3]);
int e=Integer.parseInt(args[4]);
int f=Integer.parseInt(args[5]);
double t;
int[] intArray=new int[ ]{a,b,c,d,e,f};
for
(
int i=0; i < intArray.length - 1; i++ ){
int
z=Math.min(intArray[i],intArray[i+1]
);
intArray[i+1]=z;
}
int
small=intArray[intArray.length-1];
System.out.println("The smallest number in this set is "+small);
System.out.println
(" The square
root of this number is " + Math.sqrt(small
)
+
"\n
which when rounded is " +Math.round(
Math.sqrt(small) ) );
}
}
New Math //
just for Reference
New Math Class,
StrictMath
StrictMath is a parallel
class that offers roughly the
same methods as the Math class but offers 'bit by bit
same results.' The added strictness comes at the cost
of performance. In many cases both classes are using
the same functions.
New Math
Methods //
for refererence
New Math methods have
snuck in in later versions
of the JDK. ( 1.4.x and 1.5.x )
cbrt(double a)
Returns the cube
root of a double value
cosh( double x)
Returns the hyperbolic cosine of a double value.
expm1(x)
+ 1 is
much closer to the true result of exp(x)
hypot(double x,double y)
Returns sqrt(x2 +y2)without intermediate overflow or
underflow.
log1p(double x)
Returns the natural logarithm of the sum of the
argument and 1.
signum(float f)
Returns the signum function of the argument; zero
if the argument is zero, 1.0f if the argument is greater
than zero, -1.0f if the argument is less than zero.
ulp(float f)
Returns the size of an ulp of the argument. An ulp of
afloat
value is the positive distance between this
floating-point value and thefloat
value next larger in
magnitude.
Had to try ulp( ) !
class Gulp{
public static void main(String args[]){
for(float f = 0.0F; f < 0.000000000001F ; f= f + .0000000000001F){
System.out.println(Math.ulp(f) + " ");
// Also works with no difference in this example
// System.out.println(StrictMath.ulp(f) + " ");
}
}
}
OUTPUT
> java Gulp
1.4E-45
6.7762636E-21
1.3552527E-20
2.7105054E-20
2.7105054E-20
5.421011E-20
5.421011E-20
5.421011E-20
5.421011E-20
5.421011E-20
1.0842022E-19
The Vector Class
One of the principle
drawbacks of using arrays is they
need to be fixed in length. They
don't lend themselves
to dynamically changing size. A Vector is a
Java class
that acts as a container similar to an array but one
which
can grow or shrink in size to allow objects to be added or
removed after the Vector has been created. While arrays
are a
built-in feature of the Java language the Vector class
is a regular
Java library class and will be referenced via
the java.util package.
// Vector is in the
java.util package, unlike an array it is growable
Unlike arrays, which can
be
specified for any
type defined
in Java (primitives, arrays, and Object types ),
Vectors
store one generic type, that of Object.
It is easy to add
an item to a Vector but to get it back it has
to be cast
to the appropriate type.
Vector, unlike the
String, Math and the wrapper classes
are not in the java.lang
package. To use the Vector class
the java.util package needs to be
imported or Vector's
fully qualified name needs to be used, java.util.Vector.
Example
import java.util.Vector;
// or
import java.util.*; or use fully qualified name
Following is the
class signature of the Vector class
and
it's hierarchy.
Vector Class Signature
public
class
Vector
extends AbstractList implements List, Cloneable,
Serializable
Vector Class Hierarchy
java.lang.Object
|
+--java.util.AbstractCollection
|
+--java.util.AbstractList
|
+--java.util.Vector
//
the inheritance tree shows Vector is a type of List and also implements
// the List interface A list is an ordered collection (also known
generically
// as a sequence).
A Vector is created via
one of it's four constructors. Vector has
an empty constructor and
a constructor that takes a Collection
object. It also has a constructor that allows setting the
initial
capacity of the Vector. A fourth constructor allows
specifying
the initial capacity and the capacity increment. The
capacity
increment decides the size that the vector will grow by
and is
automatically set to the size of the vector.
//
capacity is automatically set to the size of the vector
Vector implements the
methods of the List interface plus about
15 other methods for a
total of about 40 methods. This shows
you that Vector has quite a bit
of versatility absent in the array.
Classic Instantiation Form
Vector v=new Vector( 5
);
// this is a Vector
with it's initial capacity set to 5.
You
can use add( ) and addElement( ) methods to add items to
the Vector
and remove( ) or removeElement( )
methods to remove
items. Primitive types need to be
'wrapped' in appropriate wrapper
classes to be stored in a Vector.
The elements( ) method will return
an Enumeration object which you can iterate with
Enumeration's
hasMoreElements( ) and
nextElement( ) methods. elementAt( )
returns
a component at a specified index.
Evidence of Underlying Object Array
It
is interesting to note that the
Vector object will allow more items
to be added than was declared to the constructor as
the initial
capacity. But if an access is attempted beyond the last element
added, a runtime exception
ArrayOutOfBoundsException is
thrown.
This, together with the fact that Vector only takes Object type,
indicates that an Object array is used at the heart of a Vector
class. This
array is copied
to a bigger array when the stated
capacity of the Vector
is exceeded.
//
The fact an ArrayOutofBoundsException may be thrown indicates that
// Vector is
a wrapper for an array
accessorized with 'growable' algorithms
Vector
Code Sample Classic Version //
with casting
import java.util.*;
class
VectorTest{
public static void
main(String[]args){
Vector v=new
Vector(3);
Integer i1=new Integer(1);
Integer i2=new Integer(2);
Integer i3=new Integer(3);
Integer
i4=new Integer(4);
v.add(i1);
v.add(i2);
v.add(i3);
v.add(i4); // not like
array. Vector adds past capacity.
Integer five=(Integer)(v.elementAt(3));
System.out.println(five.intValue());
}
}
Attack of the
Generics!
// as of JDK 1.5
Stop right there.
That was the way we would instantiate
a collection class like a vector.
This whole idea of allowing
a general Object type to be stored made those who wanted
stricter type safety uncomfortable.
As a result
in JDK 1.5 Generics were
introduced. This
allowed
specifying precisely the type
of
objects
that
would be stored
in classes like Vector. This can include
Object type which allows the classic behaviour to remain.
The above
instantiation in the brave new world of JDK1.5
might take the look of the following.
New Generic Instantiation Form
Vector<Integer>
v=new Vector<Integer>(3);
The 1.5 equivalent of
the old form is:
Following
the
code
is rewritten with Generics. Notice
a benefit is we no longer need to cast our values back.
Vector
Code Sample With Generics // don't need the cast back
import
java.util.*;
class VectorTest{
public static void main(String[]args){
Vector<Integer> v=new Vector<Integer>(3);
Integer i1=new Integer(1);
Integer i2=new Integer(2);
Integer i3=new Integer(3);
Integer i4=new Integer(4);
v.add(i1);
v.add(i2);
v.add(i3);
v.add(i4); // not like array. Vector adds past capacity.
Integer five=v.elementAt(3);
System.out.println(five.intValue());
}
}
Constructor
Summary
// from the jdk documentation
Vector( ) |
Constructs an empty vector so that its
internal data array |
Vector |
Constructs a vector containing the
elements of the |
Vector |
Constructs an empty vector with the
specified initial |
Vector(int initialCapacity, |
Constructs an empty vector with the specified
initial |
Method
List
void add (int index, |
Inserts the specified element at the
specified position |
boolean add(Object o) |
Appends the specified element to the end of this Vector. |
boolean addAll |
Appends all of the elements in the
specified Collection |
boolean addAll |
Inserts all of the elements in in the
specified Collection |
void addElement |
Adds the specified component to the
vector end, |
int capacity() |
Returns the current capacity of this vector. |
void clear ( ) |
Removes all of the elements from this Vector. |
Object clone( ) |
new Returns a clone of this vector. |
boolean contains |
Tests if the specified object is a
component in |
boolean containsAll |
Returns true if this Vector contains all
of the |
void copyInto |
Copies the components of this vector into
|
Object elementAt(int index) |
Returns the component at the specified index. |
Enumeration elements() |
Returns an enumeration of the components
of |
void ensureCapacity |
Increases the capacity of this vector, if
necessary, |
boolean equals(Object o) |
Compares the specified Object with this
Vector |
Object firstElement( ) |
Returns the first component (the item at
index 0) |
Object get(int index) |
Returns the element at the specified
position in |
int hashCode() |
Returns the hash code value for this Vector. |
int indexOf(Object elem) |
Searches for the first occurence of the given
argument, |
int indexOf |
Searches for the first occurence of the
given argument, |
void insertElementAt |
Inserts the specified object as a
component in this |
boolean isEmpty() |
Tests if this vector has no components. |
Object lastElement( ) |
Returns the last component of the vector. |
int lastIndexOf(Object elem) |
Returns the index of the last occurrence
of the |
int lastIndexOf |
Searches backwards for the specified
object, starting |
Object remove(int index) |
Removes the element at the specified
position in this |
boolean remove(Object o) |
Removes the first occurrence of the
specified element |
boolean removeAll |
Removes from this Vector all of its
elements that are |
void removeAllElements() |
Removes all components from this vector
and |
boolean removeElement |
Removes the first (lowest-indexed)
occurrence of |
void removeElementAt |
Deletes the component at the specified index. |
protected void removeRange |
Removes from this List all of the
elements whose index |
boolean retainAll |
Retains only the elements in this Vector that
are |
Object set |
Replaces the element at the specified
position in this |
void setElementAt |
Sets the component at the specified index
of this |
void setSize(int newSize) |
Sets the size of this vector. |
int size() |
Returns the number of components in this vector. |
List subList |
Returns a view of the portion of this
List between |
Object[] toArray() |
Returns an array containing all of the
elements in |
Object[] toArray(Object[] a) |
Returns an array containing all of the
elements in |
String toString() |
Returns a string representation of this
Vector, |
void trimToSize( ) |
Trims the capacity of this vector to be
the vector's |
Self Test Self Test With Answers
1)
If used inside one of the constructors of a class called Cat
which
of the following would the constructor this( 1.1, 2.2 ) call?
a ) Cat (double x,
double y ) { /* */ }
b) Cat( int j, int k ) { /* */ }
c)
Cat( ) { /* */ }
d) Cat ( float u, int p ) { /*
*/ }
2) What will the
following print out? Select the correct answer.
String
x1
=
"X";
String x2 = "X";
if (x1.equals(x2))
System.out.println( "Positive")
else
System.out.println("Negative")
a
) Positive
b ) Negative
3) What will the
following print out? Select the correct answer.
String
x1 = "X";
String x2 = "X";
if
(x1==x2)
System.out.println(
"Positive")
else
System.out.println("Negative")
a
)
b)
4) One of the following is not a valid wrapper class. Which is it?
a)
Float
b) Int
c)
Double
d) Long
5) Which of the following statements is not correct?
a)
The Math class itself is final so can only be extended once
b) Math's constructor is private so it
cannot be instantiated.
c) Math
methods and constants are static
d)
Math methods are only accessible through the Math class name
6)
Math.floor(44.4) returns
a) 45
b) 45.0
c)
44
d) 44.0
7) Which of the following is not in the java lang package
a)
Vector
b) Boolean
c)
Math
d) String
8 ) Which of the following statements is not correct?
a)
The number of objects added may exceed the capacity.
b)
The no-args Vector constructor defaults to an initial capacity set to
5.
c) To return an element to it's
original type typically requires a cast.
d)
Vector can throw an exception is an element index is addressed
higher than the number
of elements that have been added to the
Vector.
Exercise
Using
Constructors
1 ) Create a parent
class with three different constructors. Include one
no-arg
constructor. The other two constructors will be overloaded and
takes different arguments, distinguished either by type, number
or order.
In a child class
constructor invoke one of the parent constructors that
takes
arguments using the keyword 'super'. Then in the child, use the
'this' keyword in another constructor to invoke the constructor
that has
used the 'super' keyword. Add some symbolic accessory
features to the
second constructor, even just comments or actions
represented by
System.out.println statements.
Using
Lang Classes
2) Create a class that
takes a name in at the command line. Use methods
of the String class
to convert the name to uppercase and pre- and postfix
the name
with exclamation marks. Then write to the command line the
'dressed' name in conjunction with a statement something like
"!!! BOB !!!
You have won a new car!"
3) Create two
wrapper classes that store a height and width of a right-
angled
triangle. Pass
these values in at the command line when the
program is invoked.
Store these two
classes in a Vector. Access the
Vector elements and retrieve the
wrapped values.
Figure
out the hypotenuse using Math methods and store this value in
another
wrapper class.
Access the third wrapper class and write the
three values in a
statement to screen.
(i.e. A triangle with a width of
___ and a height of ____ has a
hypontenuse value
of ______ )
//
it would be tempting to just store the final value in the Vector but
for exercise
//
we take the long way around and store the two entered values in the
Vector
//
before accessing them to compute the hypotenuse.
PS.
If you forgot the Pythagorean theorem, it states that the sum of
the
squares of of
the sides of a right angled triangle is equal to the
square of
the hypotenuse.
A 2
=
B 2
+
C 2
Optional Approaches
Using Command Line IO
You can use the
String[ ] supplied by main to enter
values to your program. There are
a couple examples
of this technique shown in the above note. This
functionality would
typically be used to configure
your application. For instance,
if your program was
creating a net connection, you could enter a port
number other than
the default.
You
may wish to use an 'inline' approach based classes
in the io package
as in the following
partial excerpt. Either
way is good to practice. The following code
is pretty
primitive.
Making it more sophisticated has the
disadvantage of making it
complex. It does
show a
formula for entering values at the command line.
import
java.io.*;
class AverageTwoNumbers
{
public static void main(String[]args)
{
String value = "";
int sum = 0;
int average = 0;
BufferedReader in = new
BufferedReader
(new
InputStreamReader(System.in));
System.out.println( " Enter a mark " );
try{
value =
in.readLine( );
int
holding = 0;
try{
holding
=
Integer.parseInt(value);
sum
=
sum + holding;
}
catch(NumberFormatException ne){
System.out.println(
"Your
number was not well
formed");
}
System.out.println(
"You have entered: " + value);
System.out.println(" Type in another value ");
value = in.readLine(
);
try{
holding
=
Integer.parseInt(value);
sum
=
sum + holding;
}
catch(NumberFormatException ne){
System.out.println(
"Your
number was not well formed. Run
again.");
return;
}
average = sum /2;
System.out.println("The average of the two numbers is: " +
average);
}
catch(IOException io){System.out.println("IOException
thrown");}
}
}
Using
JOptionPane
You
can also use the handy JOptionPane to do input and
output at the keyboard.
JOptionPane supplies a handy
lightweight GUI for entering and displaying data.
Followng
is
sample code showing JOptionPane being used. The
Double wrapper class is
also used. To add a
degree of
robustness, we add exception catching for the exception,
NumberFormatException.
JOptionPane Sample Code
import javax.swing.*;
public class
LightGUI {
public static
void main(String[]args){
try{
double
base;
double
height;
String
baseInput = JOptionPane.showInputDialog
("What is the length of the base
of the triangle?");
base =
Double.parseDouble(baseInput);
String
heightInput = JOptionPane.showInputDialog
("And what is the height of
the triangle?");
height =
Double.parseDouble(heightInput);
double
areaTriangle = base * height / 2 ;
JOptionPane.showMessageDialog
(null, "The area of your triangle is " +
areaTriangle);
}
catch(NumberFormatException
nfe){
JOptionPane.showMessageDialog
(null,
"Your number is too large or incorrectly formatted.");
}
System.exit(0);
}
}