Arrays and Strings

Preface

Students in Prof. Baldwin's Introductory Java Programming classes at ACC are responsible for knowing and understanding all of the material in this lesson (except that they are not responsible for detailed information that is specific to C++).

The detailed material on C++ is provided as supplementary material for the benefit of persons already familiar with C++ who are making the transition into Java.

Introduction

The first step in learning to use a new programming language is usually to learn the foundation concepts such as variables, types, expressions, flow-of-control, arrays, strings, etc. This lesson concentrates on arrays and strings. In some cases, these concepts, as they apply to the Java language, are compared to the same concepts for the C++ language, identifying similarities and differences.

Java provides a type for both arrays and strings from which objects of the specific type can be instantiated. Once instantiated, the methods belonging to those types can be exercised by way of the object.

Arrays

C++ has no true array type and no string type whatsoever. 

An array in C++ is simply a set of sequential memory locations that can be accessed using either indices or pointers. Regardless of the method of access, there is nothing in C++ to prevent a program from writing outside the bounds of an array and destroying the contents of memory in the process. The declaration of an array in C++ simply sets aside the requisite block of memory and treats the name of the array as a synonym for the address of the beginning of the block of memory. 

A string in C++ is simply a set of eight-bit bytes arranged in sequential memory locations with the last byte in the set forced to a value of zero. A variety of standard functions in C++ are designed to recognize this data organization as a string and to emulate the actions provided by operators on true string types in other languages. There are no provisions in C++ to prevent such a function from writing outside the bounds of the memory area intended to contain the string

Java does have a true array type and a true String type with protective features to prevent your program from writing outside the memory bounds of the array or the String. Arrays and strings are first-class objects in Java.

In Java, you must declare an array before you can use it. In declaring the array, you must provide two important pieces of information:

Arrays may be declared in Java using either of two different formats as illustrated below:
 
int[] myArray;

int myArray[];
Note that as with other objects in Java, the declaration does not allocate memory to contain the array data. Rather it simply allocates memory to contain a reference to the array.

Memory to contain the array data must be allocated from dynamic memory using statements such as the following.
 
int[] myArray = new int[15];

int myArray[] = new int[25];
These two statements simultaneously declare the name of the array and cause memory to be allocated to contain the array.

However, it is not necessary to combine these two processes. You can execute one statement to declare the array and another statement to cause the memory to be allocated as shown below.

Causing memory to be set aside to contain the array data is commonly referred to as instantiating the array object (creating an instance of the array object).

If you prefer to declare and instantiate the array at different points in your program, you can use the following syntax. This pattern is very similar to the declaration and instantiation of all objects in Java.
 
int[] myArray;

. . .

myArray = new int[25];
The general syntax for declaring and instantiating an array is as shown below.
 
typeOfElements[] nameOfArray = new typeOfElements[sizeOfArray]
Having instantiated an array in Java, you can access the elements of the array using index syntax similar to C++ and many other languages as shown below.
 
myArray[5] = 6;



myVar = myArray[5];
.
 
Unlike C++, however, Java does not permit accessing the elements of an array using pointers (Java does not support pointers). 
As in C++, array indices in Java always begin with 0.

The following code fragment illustrates another interesting aspect of arrays in Java. Note the use of length in the following code.
 
for(int cnt = 0; cnt < myArray.length; cnt++) myArray[j] = j;
All array objects in Java have a length property that can be accessed to determine the number of elements that can be stored in the array.

Arrays can contain any Java data type including reference types such as objects, or other arrays.

You need to be careful, however, in instantiating arrays of Strings. This will be discussed in a later section.

Causing an array to contain elements which are themselves arrays is a good way to construct multi-dimensional arrays in both Java and C++.

The following program illustrates an interesting aspect of the use of arrays in Java. Java can be used to produce multi-dimensional arrays, which can be viewed as an array of arrays. However, the secondary arrays need not all be of the same size.

In this program, a two-dimensional array of integers is declared and instantiated with the primary size (size of the first dimension) being three. The sizes of the secondary dimensions (sizes of each of the sub-arrays) is 2, 3, and 4 respectively.

When declaring a two-dimensional array, it is not necessary to declare the size of the secondary dimension when the array is declared. Declaration of the size of each sub-array can be deferred until later as illustrated in this program.

This program also illustrates the result of attempting to access an element which is out-of-bounds in Java. Java protects you from such programming errors.
 
In C++, when you attempt to access and store data into an array element which is out-of-bounds, you will simply succeed in storing data into an area of memory which is not part of the array
In Java, an exception occurs if you attempt to access out-of-bounds, as shown in the following sample program.

In this case, the exception was simply allowed to cause the program to terminate. The exception could have been caught and processed by an exception handler, a concept that will be explored in depth later.

The output from this program is shown in the comments at the beginning of the program.
 
/*File array01.java Copyright 1997, R.G.Baldwin

Illustrates creation and manipulation of two-dimensional 

array with the sub arrays being of different lengths.



Also illustrates detection of exception when an attempt is

made to store a value out of the array bounds.



This program produces the following output:



00

012

0246

Attempt to access array out of bounds

java.lang.ArrayIndexOutOfBoundsException:

     at array01.main(array01.java: 47)



**********************************************************/

class array01 { //define the controlling class

  public static void main(String[] args){ //main method

    //Declare a two-dimensional array with a size of 3 on 

    // the primary dimension but with different sizes on 

    // the secondary dimension.

    //Secondary size not specified initially

    int[][] myArray = new int[3][];

    myArray[0] = new int[2];//secondary size is 2

    myArray[1] = new int[3];//secondary size is 3

    myArray[2] = new int[4];//secondary size is 4



    //Fill the array with data

    for(int i = 0; i < 3; i++){

      for(int j = 0; j < myArray[i].length; j++){

        myArray[i][j] = i * j;

      }//end inner loop

    }//end outer loop



    //Display data in the array

    for(int i = 0; i < 3; i++){

      for(int j = 0; j < myArray[i].length; j++){

        System.out.print(myArray[i][j]);

      }//end inner loop

      System.out.println();

    }//end outer loop



    //Attempt to access an out-of-bounds array element

    System.out.println(

                  "Attempt to access array out of bounds");

    myArray[4][0] = 7;

    //The above statement produces an ArrayIndexOutOfBounds

    // exception.



  }//end main

}//End array01 class.  
.
 
While it may be possible to create a C++ program which mimics the behavior of this Java program by creating a special Array class, the program would be fairly complex and comparison of that C++ program with this Java program might not be very educational. Therefore, in this case, we did not provide a similar C++ program. 
Java also allows you to assign one array to another. You must be aware, however, that when you do this, you are simply making another copy of the reference to the same data in memory.

Then you have two references to the same data in memory which is often not a good idea. This is illustrated in the following program.
 
/*File array02.java Copyright 1997, R.G.Baldwin

Illustrates that when you assign one array to another 

array, you end up with two references to the same array.



The output from running this program is:



firstArray contents

0 1 2

secondArray contents

0 1 2

Change a value in firstArray and display both again

firstArray contents

0 10 2

secondArray contents

0 10 2

**********************************************************/

class array02 { //define the controlling class

  int[] firstArray;

  int[] secondArray;



  array02() {//constructor

    firstArray = new int[3];

    for(int cnt = 0; cnt < 3; cnt++) firstArray[cnt] = cnt;



    secondArray = new int[3];

    secondArray = firstArray;

  }//end constructor



  public static void main(String[] args){//main method

    array02 obj = new array02();

    System.out.println( "firstArray contents" );

    for(int cnt = 0; cnt < 3; cnt++)

      System.out.print(obj.firstArray[cnt] + " " );

    System.out.println();



    System.out.println( "secondArray contents" );

    for(int cnt = 0; cnt < 3; cnt++)

      System.out.print(obj.secondArray[cnt] + " " );



    System.out.println();

    System.out.println(

      "Change value in firstArray and display both again");

    obj.firstArray[1] = 10;



    System.out.println( "firstArray contents" );

    for(int cnt = 0; cnt < 3; cnt++)

      System.out.print(obj.firstArray[cnt] + " " );

    System.out.println();



    System.out.println( "secondArray contents" );

    for(int cnt = 0; cnt < 3; cnt++)

      System.out.print(obj.secondArray[cnt] + " " );



    System.out.println();

  }//end main

}//End array02 class.  
.

Arrays of Objects

There is one more subtle issue that you need to come to grips with before we leave our discussion of arrays. In particular, when you create an array of objects, it really isn't an array of objects. Rather, it is an array of reference variables of the object type where each element in the array can be caused to refer to an actual object of that type. The actual objects aren't really stored in the array. Rather, they are stored somewhere else in memory and the elements in the array simply refer to them.

.
 
This is different from the situation in C++. If you declare an array of objects in C++, the objects are actually stored in the array, and you can use the sizeof operator along with a pointer to traverse the array and examine the contents of the objects. 

The situation in Java is similar to what you get in C++ when you declare an array of pointer variables and then instantiate a series of objects in dynamic memory and store the pointers to the objects into the elements of the array of pointers. In C++, you can arbitrarily modify the value of any of the pointers, but you cannot arbitrarily modify the values of the references in Java.

The fact that the array is simply an array of reference variables has some very interesting ramifications.
 
For example, it isn't necessary that all the elements in the array be of the same type, provided the reference variables are of a type that will allow them to refer to all the different types of objects. 
If you declare the array to contain references of type Object, then those references can refer to any type because a reference of type Object can be used to refer to any object in Java.

If you do that, you will have to downcast the references to the proper type before you can use them to access the instance variables and instance methods of the objects, but that's no great challenge as long as you can decide what type to downcast them to.

There is a class named Vector in Java that takes advantage of this situation. An object of type Vector is a self-expanding array of reference variables of type Object. You can use an object of type Vector to manage a group of objects of any type, either all of the same type, or mixed.

Our sample program isn't quite that complicated. In this program, we simply declare a reference variable to an array of type Date.

Then we instantiate a three-element array of reference variables of type Date.

Then we display the contents of the array elements and confirm that they are all null as they should be.

Then we instantiate three objects of type Date and store the references to those objects in the three elements of the array.

Then we access the references from the array and use them to display the contents of the individual Date objects, and as you might expect from the name of the class, each object contains information about the data.

As I have stated in other lessons, becoming a successful Java programmer requires you to learn to cope with a lot of indirection.
 
/*File array03.java Copyright 1997, R.G.Baldwin



Illustrates use of arrays with objects.



Illustrates that "an array of objects" is not really an

array of objects, but rather is an array of references

to objects.  The objects are not stored in the array,

but rather are stored somewhere else in memory and the

references in the array elements refer to them.



The output from running this program is:



myArrayOfRefs contains

null

null

null



myArrayOfRefs contains

Sat Dec 20 16:56:34 CST 1997

Sat Dec 20 16:56:34 CST 1997

Sat Dec 20 16:56:34 CST 1997

**********************************************************/

import java.util.*;



class array03 { //define the controlling class

  Date[] myArrayOfRefs; //Declare reference to the array



  array03() {//constructor

    //Instantiate the array of three reference variables

    // of type Date.  They will be initialized to null.

    myArrayOfRefs = new Date[3];



    //Display the contents of the array.

    System.out.println( "myArrayOfRefs contains" );    

    for(int cnt = 0; cnt < 3; cnt++)

      System.out.println(this.myArrayOfRefs[cnt]);

    System.out.println();    

    

    //Instantiate three objects and assign references to

    // those three objects to the three reference 

    // variables in the array.

    for(int cnt = 0; cnt < 3; cnt++)

      myArrayOfRefs[cnt] = new Date();



  }//end constructor

  //-----------------------------------------------------//

  

  public static void main(String[] args){//main method

    array03 obj = new array03();

    System.out.println( "myArrayOfRefs contains" );

    for(int cnt = 0; cnt < 3; cnt++)

      System.out.println(obj.myArrayOfRefs[cnt]);

    System.out.println();

  }//end main

}//End array03 class.  
.

Strings

A string is commonly considered to be a sequence of characters stored in memory and accessible as a unit.
 
As mentioned above, C++ doesn't support a string type but simply has an agreed-upon storage format which is treated as a string. However, Java implements strings using the String class and the StringBuffer class. 
Both Java and C++ consider a series of characters surrounded by quotation marks to be a literal string, as in the following example.
 
"This is a string literal in either Java or C++."
.A major section of a subsequent lesson will be devoted to the topic of strings, so this discussion will be brief.

String objects cannot be changed once they have been created. If you have that need, use the StringBuffer class instead.

StringBuffer objects can be used to create and manipulate character data as the program executes.

String Concatenation

In C++, you can concatenate two "chunks" of string data using the standard function strcat(). When you concatenate strings in C++, you must be very careful to avoid overflowing the boundary of the destination array which is to contain the concatenated string. 
Java supports string concatenation using the overloaded + operator as shown in the following example.
 
"My variable has a value of " + myVar + " at this point in the program."
In addition to concatenating the strings, Java also converts variables such as myVar in the above example to character-string format in the process.

Arrays of String References

The following statement declares and instantiates an array of references to five string objects.
 
String[] myArrayOfStringReferences = new String[5];
Note however, that this array doesn't contain the actual string data. Rather, it simply sets aside memory for storage of five references to strings. No memory has been set aside to store the characters that make up the individual strings. You must allocate the memory for the actual string objects separately using code similar to the following.
 
myArrayOfStringReferences[0] = new String("This is the first string.");

myArrayOfStringReferences[1] = new String("This is the second string.");
In a subsequent lesson, we will discuss the ability of Java to instantiate objects of type String without the requirement to use the new operator.
 
This is similar to the common practice of allocating an array of char pointers in C++ and then causing each of those pointers to point to string data located somewhere else in memory. In C++, this is often referred to as a ragged array, because the length of one string can be different from the length of another string. 

Review

Q - Arrays and Strings are true objects in Java: True or False? If false, explain why.

A - True. Java provides a type for both arrays and strings from which objects of the specific type can be instantiated. Once instantiated, the methods belonging to those types can be exercised by way of the object.

Q - It is easy to write outsides the bounds of a String or an array in Java: True or False? If false, explain why.

A - False. Java has a true array type and a true String type with protective features to prevent your program from writing outside the memory bounds of the array or the String.

Q - In Java, you must declare an array before you can use it. In declaring the array, you must provide two important pieces of information. What are they?

A - In declaring the array, you must provide two important pieces of information:

Q - Provide code fragments that illustrate the two different syntaxes that can be used to declare an array in type int in Java.

A - Arrays may be declared in Java using either of two different syntaxes as illustrated below:
 
int[] myArray;

int myArray[];
Q - When you declare an array in Java, the memory required to contain the array is automatically allocated. True or False. If false, explain why and show how memory can be allocated.

A - False. As with other objects in Java, the declaration of an array does not allocate memory to contain the array data. Rather it simply allocates memory to contain a reference to the array. Memory to contain the array data must be allocated from dynamic memory using statements such as the following.
 
int[] myArray = new int[15];

int myArray[] = new int[25];
Q - In Java, it is required that you simultaneously declare the name of the array and cause memory to be allocated to contain the array in a single statement: True or False? If false, explain why and show code fragments to illustrate your answer.

A - False. While it is possible to simultaneously declare the name of the array and cause memory to be allocated to contain the array, it is not necessary to combine these two processes. You can execute one statement to declare the array and another statement to cause the memory to be allocated as shown below.

int[] myArray;

myArray = new int[25];
Q - Array indices in Java always begin with 1: True or False. If false, explain why.

A - False. Array indices in Java always begin with 0.

Q - What is the name of the property of arrays in Java that can be accessed to determine the number of elements that can be stored in an array? Provide a sample code fragment that illustrates the use of this property.

A - All array objects in Java have a length property that can be accessed to determine the number of elements that can be stored in the array as shown below.
 
for(int cnt = 0; cnt < myArray.length; cnt++) myArray[j] = j;
Q - What types of data can be stored in Java arrays?

A - Arrays can contain any Java data type including reference types such as objects, or other arrays.

Q - Just as in other languages, when you create a multi-dimensional array in Java, the secondary arrays must all be of the same size: True or False. If false, explain your answer. Then provide a code fragment that illustrates your answer or refer to a sample program in Baldwin's Java tutorial that illustrates your answer.

A - False. Java can be used to produce multi-dimensional arrays, which can be viewed as an array of arrays. However, the secondary arrays need not all be of the same size. See the program named array01.java in the lesson named Java028.htm. In this program, a two-dimensional array of integers is declared and instantiated with the primary size (size of the first dimension) being three. The sizes of the secondary dimensions (sizes of each of the sub-arrays) is 2, 3, and 4 respectively.

Q - Just as in other languages, when declaring a two-dimensional array in Java, it is necessary to declare the size of the secondary dimension when the array is declared. True or False? If false, explain your answer. Then provide a code fragment that illustrates your answer or refer to a sample program in Baldwin's Java tutorial that illustrates your answer.

A - False. When declaring a two-dimensional array in Java, it is not necessary to declare the size of the secondary dimension when the array is declared. Declaration of the size of each sub-array can be deferred until later as illustrated in the program named array01.java in the lesson named Java028.htm.

Q - Java allows you to assign one array to another. Explain what happens when you do this. Then provide a code fragment that illustrates your answer or refer to a sample program in Baldwin's Java tutorial that illustrates your answer.

A - Java allows you to assign one array to another. When you do this, you are simply making another copy of the reference to the same data in memory. Then you have two references to the same data in memory. This is illustrated in the program named array02.java in the lesson entitled Java028.htm.

Q - Give a brief description of the common concept of a string and list the names of two classes used to implement strings in Java?

A - A string is commonly considered to be a sequence of characters stored in memory and accessible as a unit. Java implements strings using the String class and the StringBuffer classes.

Q - What is the syntax that is used in Java to indicate a literal string? Provide a code fragment to illustrate your answer.

A - The Java compiler considers a series of characters surrounded by quotation marks to be a literal string, as in the following code fragment:

"This is a literal string in Java."

Q - Explain the difference between objects of type String and StringBuffer.

A - String objects cannot be changed once they have been created. StringBuffer objects can be used to create and manipulate character data as the program executes.

Q - Provide a code fragment that illustrates how to concatenate strings in Java.

A - Java supports string concatenation using the overloaded + operator as shown in the following code fragment:

"My variable has a value of " + myVar + " at this point in the program."

Q - Provide a code fragment that declares and instantiates an array of references to two string objects. Explain what happens when this code fragment is executed. Then show a code fragment that will allocate memory for the actual string objects.

A - The following statement declares and instantiates an array of references to two string objects.
 
String[] myArrayOfStringReferences = new String[2];
Note however, that this array doesn't contain the actual string data. Rather, it simply sets aside memory for storage of two references to strings. No memory has been set aside to store the characters that make up the individual strings. You must allocate the memory for the actual string objects separately using code similar to the following.
 
myArrayOfStringReferences[0] = new String("This is the first string.");

myArrayOfStringReferences[1] = new String("This is the second string.");
Q - Write a Java program that meets the following specification.
 
/*File SampProg10.java from lesson 28

Copyright 1997, R.G.Baldwin



Without reviewing the solution that follows, write a Java

application that illustrates the creation and manipulation of

a two-dimensional array with the sub arrays being of different

lengths.



Also cause your application to illustrate that an attempt

to access an array element out of bounds results in an exception

being thrown.  Catch and process the exception.



Display a termination message with your name. 

================================================================

*/

class SampProg10 { //define the controlling class

  public static void main(String[] args){ //define main method

    //Declare a two-dimensional array with a size of 3 on the

    // primary dimension but with different sizes on the

    // secondary dimension.

    int[][] myArray = new int[3][];//secondary size not specified

    myArray[0] = new int[2];//secondary size is 2

    myArray[1] = new int[3];//secondary size is 3

    myArray[2] = new int[4];//secondary size is 4



    //Fill the array with data

    for(int i = 0; i < 3; i++){

      for(int j = 0; j < myArray[i].length; j++){

        myArray[i][j] = i * j;

      }//end inner loop

    }//end outer loop



    //Display data in the array

    for(int i = 0; i < 3; i++){

      for(int j = 0; j < myArray[i].length; j++){

        System.out.print(myArray[i][j]);

      }//end inner loop

      System.out.println();

    }//end outer loop



    //Attempt to access an out-of-bounds array element

    try{

      System.out.println("Attempt to access array out of bounds");

      myArray[4][0] = 7;

    }catch(ArrayIndexOutOfBoundsException e){

      System.out.println(e);

    }//end catch

   

    System.out.println("Terminating, Bill Gates");     



  }//end main

}//End SampProg10 class.  Note no semicolon required