Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Arrays and Strings

Java Programming, Lecture Notes # 28, Revised 10/02/99.

Preface
Introduction
Arrays
Arrays of Objects
Strings
String Concatenation
Arrays of String References
Review

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 those persons are already familiar with C++ and who are making the transition into Java.

Introduction

The first step

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.

Array and String types

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

Arrays in C++

C++ has no true array type and no string type whatsoever (except that a string class has been proposed for the new ANSI standard). 

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

Arrays and Strings in Java

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 true objects in Java.

Declaring an array

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

Different declaration formats

Arrays may be declared in Java using either of two different formats as illustrated below:
 

int[] myArray;
int myArray[];

Declaration does not allocate memory

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.

How do I allocate memory for the data?

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.

Can declaration and allocation be separated?

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

Separating declaration from instantiation

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];

Combining declaration and instantiation

The general syntax for declaring and instantiating an array is as shown below.

typeOfElements[] nameOfArray = 
     new typeOfElements[sizeOfArray]

Accessing array elements

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];

Using pointers to access an array element in C++

Unlike C++, however, Java does not permit accessing the elements of an array using pointers (Java does not support pointers). 

What is the value of the first index?

As in C++, array indices in Java always begin with 0.

The length property of an array

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 stored in the array.

What types can you store in a Java array?

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

Cautions regarding arrays of Strings

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

Constructing multi-dimensional arrays

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

Odd-shaped multi-dimensional arrays

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.

Can declare the size of secondary dimension later

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.

Accessing an array out-of-bounds in Java

This program also illustrates the result of attempting to access an element that is out-of-bounds in Java. Java protects you from such programming errors.

Accessing an array out-of-bounds in C++

In C++, when you attempt to access and store data into an array element that is out-of-bounds, you will simply succeed in storing data into an area of memory that is not part of the array

ArrayIndexOutOfBoundsException

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 sample program

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.  

Protecting against out-of-bounds errors in C++

While it may be possible to create a C++ program that 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. 

Assigning one array to another array -- be careful

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.

Sample program to illustrate assignment of arrays

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

An array of objects in Java really isn't an array 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's 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.

An array of objects in C++

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.

All the elements in a Java array of objects need not be of the same actual type

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.

You can do similar things using interface types. I will discuss interface types in a subsequent lesson.

Usually need to downcast to use an Object reference

If you do that, you will usually need to downcast the references to the true type before you can use them to access the instance variables and instance methods of the objects.

That's no great challenge as long as you can decide what type to downcast them to.

The Vector class

There is a class named Vector in Java that takes advantage of this capability. 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.

A sample program using the Date class

This sample program isn't quite that complicated. This program behaves as follows:

As you might expect from the name of the class, each object contains information about the date.

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

What is a string?

A string is commonly considered to be a sequence of characters stored in memory and accessible as a unit.

What is a string in C++?

As mentioned above, C++ doesn't support a string type but simply has an agreed-upon storage format, which is treated as a string.

What is a string in Java?

Java implements strings using the String class and the StringBuffer class.

What is a string literal?

Both Java and C++ consider a series of characters surrounded by quotation marks to be a string literal, as in the following example.

"This is a string literal in either Java or C++."

This is just an introduction to strings

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 modified

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

String concatenation in C++

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 that is to contain the concatenated string.

String concatenation in Java

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

Coercion of the right operand to a String

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

Declaring and instantiating a String array

The following statement declares and instantiates an array of references to five string objects.

String[] myArrayOfStringReferences = new String[5];

No string data at this point

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.

Allocating memory to contain the String objects

myArrayOfStringReferences[0] = new String(
    "This is the first string.");
myArrayOfStringReferences[1] = new String(
    "This is the second string.");

The new operator is not required for String class

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.

Arrays of pointers of type char in C++

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 
    //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
    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
    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, Dick Baldwin");     

  }//end main
}//End SampProg10 class.  Note no semicolon required

-end-