We have seen that
Java has two general type categories,
the
primitive and reference types. In the reference category,
Java supplies three complex data
structures for us to use.
We now have fourth complex data type, the enum, as of
JDK 5.
The enum is not
used with references since it is all static
so we need to create a new category for it.
We are familiar
with the class and have seen it is the main
unit of containment in the language. We also have seen in
the keywords that there is an interface
type that provides a
place to define a set of abstract methods. A third major
reference type Java supplies is the array.
Java
Types
Primitive
Types |
Reference Types | Complex Non-
Reference Type // jdk 1.5 |
|
|
-a type of it's own -it allows the user to define sets of values associated with a named type akin to the class when it is used in it's static mode. |
Enums // for reference
from JDK 1.5 docs http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html public enum Planet { MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e+26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7), PLUTO (1.27e+22, 1.137e6); private final double mass; // in kilograms private final double radius; // in meters Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } public double mass() { return mass; } public double radius() { return radius; } // universal gravitational constant (m3 kg-1 s-2) public static final double G = 6.67300E-11; public double surfaceGravity() { return G * mass / (radius * radius); } public double surfaceWeight(double otherMass) { return otherMass * surfaceGravity(); } // a main( ) method is added to reference some // of the defined data You would probably reference // the enum from another class but the enum is happy // to host the main( ) method! .ed public static void main(String[] args){ System.out.println(Planet.MERCURY.mass()); System.out.println(Planet.EARTH.radius()); System.out.println(Planet.JUPITER.surfaceGravity()); } } |
Description
of the Array
The Array is Uniform in Type
The array is uniform in
that all the elements it stores
must
be of the same type. The array offers the
Java programmer
a way to reference a single object
that represent a numbered
collection of elements. The
array in Java is a
class-like
structure however it is more restricted
in how it can be
used.
Arrays, like classes assigned
to references. They also
use the 'new' operator.
Arrays descend from Object like
the class. Arrays allow the user to control some
aspects
of their creation. For instance, the user
defines
the arrays
identifier,
designates what type of element the array
will hold and decides how many elements
the array will
contain.
Arrays have an Index
The array has an index
that can be used to
access
individual elements that have been stored
in the array.
The array also
provides a variable called 'length' that
will report
how big
the array is.
Like classes
arrays can also be passed into and
returned from
methods.
Example Showing an Array Passing In and Out of a Method
abstract class AA{
abstract int[ ] change(double[ ] doubleRay);
}
Features That Arrays &
Classes Share
Arrays
Are More Limited Than Classes
Beyond these features, the array does not supply the
sort of programming freedom that the class provides.
The user cannot define custom methods or
fields for
an
array. Further creating subclasses of arrays to create
more
specialized versions is not possible. Unlike the
class the array is a
dedicated entity which holds a
collection of
primitives, objects
or other arrays.
Array
are Unlike Classes in That They :
Arrays are More Primitive Than the
Class
Characterizing the array as a 'sort of' class
type is
somewhat artificial. Arrays predate the
invention
of
object-oriented thinking. Arrays are defined at very
basic levels of the computer where a specific number
of sequential memory cells are referred to by a starting
address in memory. Arrays underpin many of the
classes we use in Java, such as the Vector class.
// arrays underpin classes such as
'Vector' and 'ArrayList'
Arrays Underlie Other Collection Types
The modern alternatives to the array
are container classes
like the classic Vector and newer classes
defined
in the
collection package such as the ArrayList. These classes,
though they add many new functionalities, are still
internally
dependent on the array.
Key Elements of an Array
Array Declaration
Arrays are not defined like we define classes. The
array
has a fixed form that the Java programmer makes use of.
To create an array, we proceed directly
to the declaration,
instantiation and
assignment stages. In this cycle of
events,
arrays are very much like classes.
The symbols that
array's use in their constructors are
a pair of closed
square brackets (instead of the round
brackets used in methods and class
constructors.)
Using these brackets with a type specifier and an
identifier and we have the
formula for an array
declaration.
Array
Declaration Example
int I [ ];
//
arrays are characterized by the
use of square braces
There is an
ambivalence to array declaration that Java
has inherited from the 'C' programming language. The
square
braces can be on either side of the identifier. The
above and below declarations of
an int array called 'I'
are equivalent. For simple array
declarations either
way
will do.
At this point, like
with the declaration of a reference type,
a memory
container has to be declared for an address.
Declared in class scope, this
reference hold
null at this
time.
Alternative Form Example
int[
] I;
Construction
Like a class, the
array may make use of the 'new' keyword.
It mimics
the appearance of a constructor except that square
brackets are used. The array also must know how big it will
be so the size needs to be specified at construction as
well.
Example
int I []; // declaration
I = new int [15]; // instantiation includes setting array size
The next example
shows that the size of the array can be
specified with
a variable.
Example
int size = 20;
I = new int [size];
As with classes, it
is common to see the declaration,
instantiation
and assignment of an array happen in a
single step.
Example
double[ ]
dray = new double [12];
With respect to the
double array in above example, when
instantiation
and assignment has been completed, there
will be an ordered set of 12 locations
reserved in memory,
each able to hold a value of double type.
Arrays Can Have Any Primitive or Class Type
Above
we have seen arrays made based on primitive types.
Arrays are 'universal' in that they can be made of any class
type as well.
Example
Object[ ] object;
Integer[ ] integer;
// an object-oriented wrapper class for a
single int value
Arrays The Default
Values of It's Declared Type
When first
constructed, array
elements are initialized to the
default values for the
type the array contains. For 'double', the
default value is 0.0 so each element of this array will hold 0.0.
If this were
a String array, default value for a reference type is
null so each element of an
array
of type String would hold the
null value.
Unlike basic
primitives, arrays declared locally have default
values assigned. The following example shows this.
Example
class RD{
void local( ){
int[] i=new int[1];
System.out.println(i[0]);
}
public static void main(String[] args){
new RD().local();
}
}
//
arrays have default values whether
// declared in class scope or
locally
Initializations
Arrays can be
initialized with a set of literals or each
array
element can be initialized individually. The array
literal is created by
placing a comma-separated
list of
literals having the appropriate type inside enclosing
curly braces. In the first
example below you can see
the three literals contained between the curly braces
and
separated by commas. A comma after the "three"
literal value will be ignored.
Assignment
by Literals Example 1
String[ ] s = { "one", "two", "three" };
In the second
example a double array being
assigned
literally.
Assignment by Literals Example 2
double[ ] d = { 1.1, 2.2, 3.3, 4.4, 5.5 };
Notice there is no
need to establish the number of
elements the
array holds as the array 'knows' how
long it is by the number of elements it has been
assigned.
The following
example shows array elements being
initialized by
explicit assignments.
Explicit Assignment
Example
int[ ] few = new int[2];
few[0] = 25;
few[1] = 50;
This is the first time we have used the arrays
indexing
mechanism. Notice the array starts at the
offset
value
of 0. There
are two elements in the above array example
and they are referenced by the
index values 0 and 1.
Often a loop will be
used to assign values to each
element of an array, deriving the index value from the
loop's variable, as shown in the next
example.
Example of a Loop Using an Array
Index
short [ ] cubes = new short[25];
for( int i =0; i < cubes.length; i ++){
cubes[i] = i * i * i;
}
Sometimes
after the release of the first version of the
Java Development
Kit, an array creation
expression
was introduced. It
combines features of both array
forms introduced above, the literal assignment form
and the instantiated form. It seems to be a little redundant
but it has some particular uses and you may encounter
this form. It has the following
form.
Array
Creation Expression Form
new types[ ] { literal values . . . } ;
We can create a
three element byte array to show this
form. As with literal assignments the braces end with
a semi-colon.
Example
byte[ ] b = new byte[ ] { 5, 5, 5 };
// an array expression statement used in an assignment
The same result can
be obtained by just assigning the
literal.
Example
byte[ ] b =
{ 5, 5, 5 };
One Benefit of the Array Creation Expression
So why bother?
There is at least one problem this form
serves to get rid off. For
some reason an array literal can't
be assigned to a reference that has been
declared in a
previous statement.To see what I mean run the following
code.
Problem Example
class Quirk {
public static void main(String[] args){
byte bee[ ];
bee ={ 5, 5, 5 };
System.out.println(bee[0] +
" " +bee[1] );
}
}
// doesn't
compile & same thing happens using a constructor
The
compiler reports that bee ={ 5, 5, 5 }; represents an
illegal start
of an expression. However, if the same thing
is done using the form of the array creation
expression
everything is 'rosy'.
Solution Example
class Quirk {
public static void main(String[] args){
byte bee[ ];
bee =new byte[]{ 5, 5, 5 };
System.out.println(bee[0] +
" " +bee[1] );
}
} // using the array creation
expression works fine
This may be useful to remember for the times you
wish
to declare an array in class scope but
assign literal values
in
a constructor or a
method.
There are two very important methods that can
be used to
work with arrays. The first is defined
'way
back' in Object
class.
Recall arrays descend from Object class.
As
such,
they inherit the clone( )
method. The other important array
method, arraycopy( ),
is defined in System class.
clone( )
The clone( )
method can be used to make an exact copy of
an array. It has the following signature.
The
clone( ) Method Signature Defined in Object Class
protected Object clone( ) throws
CloneNotSupportedException
CloneNotSuported Exception is thrown to indicate that the clone( ) method in class 'Object's has been called to clone an object, but that the object's class does not implement the cloneable interface. A class implements the cloneable interface to indicate to the Object.clone( ) method that it is legal for that method to make a field-for-field copy of instances of that class. By convention, classes that implement this interface should override Object.clone ( which is protected ) with a public method. |
The clone( )
method is defined in Object and accordingly
is
defined as returning Object type. This
means that any
array that has been cloned must be
cast back to the type
that it originally
was. For following example shows how
clone can be used.
Example
int
Z [] = new int [ ]{ 1, 9, 11 };
int Y [] = (int [ ] ) Z.clone(
); //
clone returns Object type
Y array will be a perfect copy of Z containing
the values
1, 9, & 11. The type
in brackets, (
int [ ]
) ,
is
a cast
to the int array type. and changes the
method's return
value back to
the appropriate type, here an int array.
arraycopy( )
The arraycopy( ) method is in the System
class. It can
copy all or part of the array. It is
important
as it can be
used to get
around the fact that arrays are not growable.
For instance if an array was full or near full, it's values
could be
transferred to another array that was defined
to be bigger.
The Vector class
has this growable
feature which you
could bring to your own class definitions using arraycopy( ).
The
arraycopy method is a
static method. Recall again,
that a
static
method may be called off of it's class name.
Following is the
method signature as it is
defined in the
documentation for the System class.
The
arraycopy( ) Method Signature
public static void arraycopy(Object src, int
src_position,
Object dst, int dst_position, int length)
// Following is the JDK
documentation's description of
// what the method does.
"Copies an array from the
specified source array,
beginning at the specified position, to the specified
position of the
destination array .... The number of
components copied is equal to the
length argument.
The
components at positions srcOffset through
srcOffset + length -1 in the source array are copied
into positions dstOffset through dstOffset + length -1,
respectively
of the
destination array."
//
think offset positions when reading this quote
To show what the
method does consider two arrays. The
first we can
define two String arrays one with four elements
and the second with six elements. Note the array
statement
needs to end with a semicolon. We will use the identifiers
from the
above the arraycopy signature so it is clear what
we are doing.
Example of Two String Arrays
String[] src = new
String[]
{ "Left", "Right","Young",
"Old",
"Downtown", "Uptown"};
String[] dest = new String[]
{ "London ","Glasgow",
"New",
"York"};
Suppose we wish to
copy two elements from the 'src' array
over to 'dest'
array. The length is set to two, reflecting the
number of elements that
will be copied
over. If we want the
two elements copied to be "Old" and "Downtown" the offset
we enter at
src_position will be 3, (counting "Left" as 0). To
put these elements into the
first two locations of the 'dest'
array the offset at dst_position is set to 0. The method takes
the following shape.
Example
System.arraycopy( src, 3, dst, 0, 2);
//
The
second array will then contain
// {"Old", "Downtown", "New", "York"}
To example the
clone( ) method, we copy the dst array
into another
array and output it to screen to show how
clone( ) can be used to make a perfect
copy of an
array.
Example
class NewYork{
public static void main(String[] args){
// two String
arrays
String[ ] src = new String[ ]
{ "Left", "Right","Young",
"Old", "Downtown", "Uptown"};
String[ ] dst = new String[ ]
{ "London ","Glasgow",
"New", "York"};
// the method
arraycopy() is demonstrated
System.arraycopy( src, 3, dst, 0, 2);
System.out.println
("New Array: " + dst[0] + " " + dst[1] + " " +
dst[2] + " " + dst[3]);
// the clone() method is used to duplicate the dst array
String[] twin= ( String[] ) dst.clone( );
System.out.print("Clone's Output: ");
for(int i=0; i <twin.length; i++)
System.out.print(
twin[i] + " " );
// another loop preview
}
}
OUTPUT
> java NewYork
New Array: Old Downtown New York
Clone's Output: Old Downtown New York
Arrays can be built
of primitives and object types as we
have seen
in the earlier examples. Arrays can also be
built to contain other arrays. This leads
to the idea of
multi-dimensional arrays. The Java language experts
prefer describing compound
arrays as 'arrays of arrays'.
Following are three
compound array declarations.
Notice
again the ambivalence as to where the square braces
are put.
Example
double _2D [ ][
];
// is the same as
double[ ][ ] _2D;
or double [ ] _2D [ ] ; // declares an array of an arrays of doubles
Where the braces
are placed becomes significant when
declaring
multiple references in a single line. In the next
example, the first line declares int
arrays i an j which is
the same as declaring them separately.
Example
int
[ ] i, j:
// is the same as if we had declared i and j separately
Example
int
[ ] i;
int [ ] j;
But consider the following example.
Example
int [] k, l[], m[][];
The way to interpret this is the type to the
left of the first
identifier is distributed over the other
references declared.
Doing this
interpretation, the above declaration factors
to the following.
int [] k;
int [][] l;
int [][][] m;
// the first part of the
multiple array declaration, int [] ,
// is the overall type that distributes across
whatever is
// adjoined to the subsequent variables
Following is an
example of declaration, instantiation and
assignment
being performed for a multi-dimensional array.
This is a declaration of an array of
arrays of the class type
Ford where there is an array of 9 elements which each
holds a sub array
of 5 elements.
Example
Ford fords[ ][ ] = new Ford[9][5];
The sub arrays
are not limited to a single size. Here's
an array
creation that conceptually describes an inverted
triangle where each sub array is a different
size.
Example
int triangle[ ][ ]= new int[ ][ ]{
new int[ ]{ 3,3,3,},
new int[ ]{ 2,2},
new int[ ]{ 1},
};
We can give this triangle a simpler form by
converting
it to a classic, literally assigned, compound array.
Example
int triangle[ ][ ]={
{ 3,3,3,},
{ 2,2},
{ 1},
};
Because the second arrays do not have to be a
uniform
size, the array does not have to be declared
showing
sizes for the second arrays
however it is still neccessary
to show the size of the principle array.
Example
int[][] matrix = new int[7 ][ ] ;
// int[][] matrix = new
int[ ][0]; // not legal
This works fine in
a literal assignment form, but can
lead to troubles in assignment if the creation of the
rest of the complex array is not complete.
Example
class Tr1{
public static void main(String[] args){
int[][] triangle = new int[3][ ];
triangle[0][0]=6;
}
}
//
compiles but leads to a
NullPointerException at Runtime
// sub-arrays must be assigned to the top-level array first
The following approach completes the job of establishing
the compound arrays structure. An array instantiation is
to each element of the top-level array.
Example
class
Tr2{
public static void main(String[] args){
int[][] triangle = new int[3][ ];
triangle[0]=new int[7];
triangle[1]=new int[5];
triangle[2]=new int[3];
triangle[0][0]=6;
triangle[2][2]=19;
}
}
Assignment and referencing Arrays of Arrays
We have already
seen examples of assignments
to compound arrays. To change the above triangle
example, we could assign
individual elements of the
array as follows. The println( ) statement that
follows
shows
examples of the array being accessed.
Example
Arrays can store
primitives, other arrays and reference
types. We
have seen all of these, whether the type has
been int, another array or the String
class. The array in
all these cases acts as a container with compartments
that store uniform types. An array can also be declared
of generic Object type.
This can be very
useful as Object type
can be used to
represent any class or array. When it comes to Object
arrays, the
strict uniformity that characterizes an array
seems to blur because you can store a String, a Vector
a JButton all in
the same array. However, strict uniformity
is still present in that they all are Object type.
//
Object arrays enable the storage of various class types
The array in this
case is
just storing all the reference
addresses that point to these object types in memory.
These addressed
are all typed to generic Object class.
This leads to the situation we saw with the
return type
of the clone method where a cast was needed to convert
the object back to the
specialized type that was stored
in the first place.
//
need to do casts to retrieve original types
Still Object arrays
are limited from storing primitive numbers.
Primitives
cannot be assigned to reference types. The creators
of Java
have supplied Wrapper classes for all the primitive
types to enable storing primitives types as objects. These
convenience classes provide
a reference type wrapper that
can be used to encapsulate a primitive value. The wrapper
classes also many convenience methods to convert the
number between different types.
//
use wrappers for primitives
The
following summarizes the wrapper classes available
for the primitive types.
Primitive
Type |
Corresponding
Wrapper Class |
|
|
Getting back to an
array of Object type, such an an array
could be
used to store an an account number (stored in
a wrapper class), followed by String
objects representing
a person's name and address. As an example we can
wrap an int in it's
corresponding wrapper class, Integer.
Example
Integer accountNo = new Integer( 918924 );
The following class
shows how a number and a reference
type can be
stored in an array and retrieved making use
of a wrapper class. Don't worry about
the details of the
wrappers at this point since we haven't covered them.
The main thing to notice is the array is
more flexible for
storing data then one might have thought at first glance.
Example
class NO_ID{
public static void main(String[] args){
Object[] oo=new Object[2];
Integer accountNo = new Integer( 918924 );
String name="Tim Horton";
oo[0]=accountNo; // going in
oo[1]=name;
Integer acct=(Integer)oo[0]; // coming right back out
String person=(String)oo[1];
System.out.println( person + " " +
acct.intValue( ) );
}
}
Using Arrays with References
Sometimes you will
have a large number of object references
you want
to declare using an array of references. Often you
will use a loop to do the
initialization.
Example
class Wrap10
{
public static void
main(String[]args)
{
System.out.println("The numbers wrapped as objects are: \n " );
Integer [] numberObject =new Integer[10] ;
for(int i=0; i<10; i++)
{
numberObject[i]= new Integer(i);
System.out.println(" "+ numberObject[i].intValue( ) );
}
}
}
The next code
example demonstrates many of the points
we have discussed. We also make use of the 'instanceof'
operator.
The three classes
A, B and C are defined at the end of
the source
code. Each has a method returning a word.
In the body of the ATA class, which all
occupied by
the main( ) method an object array is created and an
instance of
each class is added to each element of the
array. For good measure, a String array is
added as well.
The 'instanceof' keyword is used in the for loop to
determine if
the actual type of the object stored at the
element location.
Code Example
class ATA{
public static void main(String[]args){
Object [] mix=new Object[ 4];
A a=new A(
);
B b=new B( );
C c=new C( );
String [] s={"cat", "dog", "parrot"};
// the class objects are
stored along with a String array in each element
// of the Object array. At this stage all are stored as generic Object
type
mix[0]=a;
mix[1]=b;
mix[2]=c;
mix[3]=s;
// here is an example of
the keyword instanceof being used to determine
// the
specific type of the object represented as an Object type in the
array.
for(int
i=0;i<3;i++){
if(mix[i] instanceof A) // selecting for the class calling th go method
System.out.print( ((A)mix[i]).go( ) );
if(mix[i]
instanceof B)
System.out.print( ((B)mix[i]).go( ) );
if(mix[i]
instanceof C)
System.out.print( ((C)mix[i]).go( ) );
String[] sx=
(String[])mix[3];
//referencing the array elements
System.out.println(sx[i]);
}
}
}
// three classes with a
method
each which return a different word
class A {
String go( ){
return " Bad ";
}
}
class B {
String go( ){
return " Friendly ";
}
}
class C {
String go( ){
return " Noisy ";
}
}
Method Forms With Arrays as Return Types
A final point, an
array can be returned from a method
as the
following example shows.
Form Example
1
int[ ] method( )
{
return new int[9];
}
The ambivalence we encountered earlier remains
with methods as well. The square braces can be
put on either
side of the
identifier.
Form Example
2
int method( )[ ]{
return
new int [11]; }
This is a legal style that looks a little odd, but it
is
familiiar to the veteran 'C' programmer
where this
form is commonly used.
This is a also a legal Java
style and in a few
APIs you can find examples of
this style
being used.
Keeping the Square Braces To Left of Method
Name
The argument against using the latter of the
two forms
is it is easy for a person reading your
code to miss the
embedded square brackets
and assume the method
returns an int rather
than an int array.
1) Which of the
following is not a Java reference type
a) interface
b) array
c) class
d) primitive
2) Arrays do
not have one of the following features in
common
with classes
a) declaration,
instantiation and assignment
b) use of the new operator
c) use of references
d) ability to define custom methods
3 ) Place the following steps in the order they would occur.
a ) initialization
b) instantiation
c ) declaration
d) assignment ___
___ ___ ___
4) Which of the following features is not found in arrays
a) a final variable
called length
b) an offset index starting at 0
c) a way to increment an arrays size as needed
d) default value assignments
5) Which of the following will not compile
a) String s =new
String[8];
b) short [2] k;
c) byte b[ ] = new byte{ 2,2,};
d) long[] l =new long{ 3L,4L, 5L };
6. The following example is the same as which of the following?
Example int [] x, [ ] l;
a ) int [] x;
int [] l;
b ) int [][]
x;
int [][] l;
c ) int [] x;
int [][] l;
d ) int [][]
x;
int [] l;
7. Which of the following is not legal?
a) byte
[]gallons[]= new byte{ 44,33,22 };
b) byte []quart[]=new byte[22][11];
c) byte pints[][]=new byte[11][ ];
d) byte [][] liters={ {1}, {2} };
8. Which of the following is not legal?
a) Object[]
obee1=new Object[]{ "String", "9" };
b) Object[] obee2= {"X",vector,array};
c ) Object[] obee3= { new Integer( 9 ), new Integer(11) };
d ) Object[] obee4= { "tractor" ,91823 };
1) In a single line
declare, instantiate and assign a three element
array for each of Java's primitive types. Intialize each element
with a value. You can use the following example to get you
started.
Example
2) In a new class
repeat the above
exercise using the classic
literal assignment technique. A literal assignment
example
is shown below.
Example
float[] f={
1.23,2.34,3.45 };
3) Create a third class that does the above only using
the array creation expression form. An example of this
form is shown below.
Example
double d= new
double[]{1.1,2.2,3.3};
5) Compile and run the following class. Then,
adapt the
code to create a new array of arrays
whose values
will
be printed to screen.
Your class will contain three fictitious
warehouses,
named by a different country where
each
might exist. For each warehouse create
subarrays
containing string literals
describing the five most important
items stored at the warehouse.
Write compile and run the
new
class so that these values are printed to
screen.
// It is not neccessary to use the Example
as a template if you
// prefer to 'clean sheet' your answer
Example
class Seasons{
public static void main(String[] args){
String[][]
seasons = new String[4][ ];
// main array size is set but subarrays can vary in size
String[]
Winter=new String[]{"Jan","Feb","Mar"};
String[] Spring=new String[]{"Apr","May","June"};
String[] Summer=new String[]{"July","Aug","Sept"};
String[] Fall=new String[]{"Oct","Nov","Dec"};
seasons[0]=Winter;
seasons[1]=Spring;
seasons[2]=Summer;
seasons[3]=Fall;
for(int
i=0;i<seasons.length;i++){
for(int j=0;j<3;j++){
System.out.println(seasons[i][j]);
}
}
}
}
6) Rewrite the following class so that it
printout NOT TRUE.
class
arrayCopy{
public static void main(String[] args){
String[] statement = new String[] { "It's", "not",
"true", "it", "was", "my", "plan"};
String[] out_of_context= new String[ 4];
System.arraycopy(statement, 3, out_of_context, 0, 4);
for(int i=0; i
<out_of_context.length; i++)
System.out.print(out_of_context[i]+" ");
System.out.println("\n");
}
}