Data Types, Variables, and Arrays
Java is a Strongly Typed Language which means that in Java every variable has a type, every expression has a type, and every type is strictly defined. All assignments, whether explicit or via parameter passing in method calls, are checked for type compatibility. The Java compiler checks all expressions and parameters to ensure that the types are compatible. Any type mismatches are errors that must be corrected before the compiler will finish compiling the class. For example, in C/C++ you can assign a floating-point value to an integer. In Java, you cannot. .
The Simple Types
Java defines eight simple types of data: byte, short, int, long, char, float, double, and boolean. These can be put in four groups:
- Integers: This group includes byte, short, int, and long, which are for whole valued signed numbers.
- Floating-point numbers: This group includes float and double, which represent numbers with fractional precision.
- Characters: This group includes char, which represents symbols in a character set, like letters and numbers.
- Boolean: This group includes boolean, which is a special type for representing true/false values.
They form the basis for all other types of data that you can create. The simple types are defined to have an explicit range and mathematical behavior. Because of Java’s portability requirement, all data types have a strictly defined range. For example, an int is always 32 bits, regardless of the particular platform.
Integers
Java defines four integer types: byte, short, int, and long. All of these are signed, positive and negative values. Java does not support unsigned or positive-only integers. The width and ranges of these integer types vary widely, as shown in this table:
Name | Width | Range |
long | 64 | –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
int | 32 | –2,147,483,648 to 2,147,483,647 |
short | 16 | –32,768 to 32,767 |
byte | 8 | –128 to 127 |
byte
The smallest integer type is byte. This is a signed 8-bit type that has a range from –128 to 127. Variables of type byte are especially useful when you’re working with a stream of data from a network or file. Byte variables are declared by use of the byte keyword. For example, the following declares two byte variables called b and c:
byte b, c;
short
short is a signed 16-bit type. It has a range from –32,768 to 32,767. Here are some examples of short variable declarations:
short s;
short t;
int
The most commonly used integer type is int. It is a signed 32-bit type that has a range from –2,147,483,648 to 2,147,483,647. In addition to other uses, variables of type int are commonly employed to control loops and to index arrays. Any time you have an integer expression involving bytes, shorts, ints, and literal numbers, the entire expression is promoted to int before the calculation is done. The int type is the most efficient type, and it should be used most of the time when you want to create a number for counting or indexing arrays or doing integer math.
Long
long is a signed 64-bit type and is useful for those occasions where an int type is not large enough to hold the desired value. The range of a long is quite large. This makes it useful when big, whole numbers are needed. For example, here is a program that computes the number of miles that light will travel in a specified number of days.
// Compute distance light travels using long variables.
class Light {
public static void main(String args[]) {
int lightspeed;
long days;
long seconds;
long distance;
// approximate speed of light in miles per second
lightspeed = 186000;
days = 1000; // specify number of days here
seconds = days * 24 * 60 * 60; // convert to seconds
distance = lightspeed * seconds; // compute distance
System.out.print(“In ” + days);
System.out.print(” days light will travel about “);
System.out.println(distance + ” miles.”);
}
}
This program generates the following output:
In 1000 days light will travel about 16070400000000 miles. Clearly, the result could not have been held in an int variable.
Floating-Point Types
Floating-point numbers, also known as real numbers, are used when evaluating expressions that require fractional precision. For example, calculations such as square root, sine and cosine, result in a value whose precision requires a floating-point type. There are two kinds of floating-point types, float and double, which represent single and double-precision numbers, respectively. Their width and ranges are shown here:
Name | Width | Range |
double | 64 | 4.9e–324 to 1.8e+308 |
float | 32 | 1.4e−045 to 3.4e+038 |
float
The type float specifies a single-precision value that uses 32 bits of storage. Variables of type float are useful when you need a fractional component. For example, float can be useful when representing dollars and cents. Here are some example float variable declarations:
float hightemp, lowtemp;
double
Double precision, as denoted by the double keyword, uses 64 bits to store a value. All math functions, such as sin( ), cos( ), and sqrt( ), return double values. When you need to maintain accuracy over many iterative calculations, or are manipulating large-valued numbers, double is the best choice. Here is a short program that uses double variables to compute the area of a circle:
// Compute the area of a circle.
class Area {
public static void main(String args[]) {
double pi, r, a;
r = 10.8; // radius of circle
pi = 3.1416; // pi, approximately
a = pi * r * r; // compute area
System.out.println(“Area of circle is ” + a);
}
}
Characters
In Java, the data type used to store characters is char. Java uses Unicode to represent characters. Unicode defines a fully international character set that can represent all of the characters found in all human languages. For this purpose, it requires 16 bits. Thus, in Java char is a 16-bit type. The range of a char is 0 to 65,536. There are no negative chars. The standard set of characters known as ASCII still ranges from 0 to 127. Since Java is designed to allow applets to be written for worldwide use, it makes sense that it would use Unicode to represent characters. Here is a program that demonstrates char variables:
// Demonstrate char data type.
class CharDemo {
public static void main(String args[]) {
char ch1, ch2;
ch1 = 88; // code for X
ch2 = ‘Y’;
System.out.print(“ch1 and ch2: “);
System.out.println(ch1 + ” ” + ch2);
}
}
This program displays the following output:
ch1 and ch2: X Y
Notice that ch1 is assigned the value 88, which is the ASCII and Unicode value that corresponds to the letter X. As mentioned, the ASCII character set occupies the first 127 values in the Unicode character set. Even though chars are not integers, in many cases you can operate on them as if they were integers. This allows you to add two characters together, or to increment the value of a character variable. For example, consider the following program:
// char variables behave like integers.
class CharDemo2 {
public static void main(String args[]) {
char ch1;
ch1 = ‘X’;
System.out.println(“ch1 contains ” + ch1);
ch1++; // increment ch1
System.out.println(“ch1 is now ” + ch1);
}
}
The output generated by this program is shown here:
ch1 contains X
ch1 is now Y
In the program, ch1 is first given the value X. Next, ch1 is incremented. This results in ch1 containing Y, the next character in the ASCII and Unicode sequence.
Booleans
Java has a simple type, called boolean, for logical values. It can have only one of two possible values, true or false. This is the type returned by all relational operators, such as a < b. boolean is also the type required by the conditional expressions that govern the control statements such as if and for. Here is a program that demonstrates the boolean type:
// Demonstrate boolean values.
class BoolTest {
public static void main(String args[]) {
boolean b;
b = false;
System.out.println(“b is ” + b);
b = true;
System.out.println(“b is ” + b);
// a boolean value can control the if statement
if(b) System.out.println(“This is executed.”);
b = false;
if(b) System.out.println(“This is not executed.”);
// outcome of a relational operator is a boolean value
System.out.println(“10 > 9 is ” + (10 > 9));
}
}
The output generated by this program is shown here:
b is false
b is true
This is executed.
10 > 9 is true
when a boolean value is output by println( ), “true” or “false” is displayed. Second, the value of a boolean variable is sufficient, by itself, to control the if statement. There is no need to write an if statement like this:
if(b == true) …
The outcome of a relational operator, such as <, is a boolean value. This is why the expression 10 > 9 displays the value “true.”
String Literals
String literals in Java are specified like they are in most other languages by enclosing a sequence of characters between a pair of double quotes. Examples of string literals are
“Hello World”
“two\nlines”
“\”This is in quotes\””
Table 3-1 shows the character escape sequences. The escape sequences work the same way inside of string literals. One important thing to note about Java strings is that they must begin and end on the same line. There is no line-continuation escape sequence as there is in other languages.
Escape Sequence | Description |
\ddd | Octal character (ddd) |
\uxxxx | Hexadecimal UNICODE character (xxxx) |
\’ | Single quote |
\” | Double quote |
\\ | Backslash |
\r | Carriage return |
\n | New line (also known as line feed) |
\f | Form feed |
\t | Tab |
\b | Backspace |
Table 3-1. Character Escape Sequences |
Variables
The variable is the basic unit of storage in a Java program. A variable is defined by the combination of an identifier, a type, and an optional initializer. In addition, all variables have a scope, which defines their visibility, and a lifetime.
Declaring a Variable
In Java, all variables must be declared before they can be used. The basic form of a variable declaration is shown here:
type identifier [ = value][, identifier [= value] …] ;
The type is one of Java’s types, or the name of a class or interface. The identifier is the name of the variable. You can initialize the variable by specifying an equal sign and a value. the initialization expression must result in a value of the same or compatible type as that specified for the variable. To declare more than one variable of the specified type, use a comma-separated list. Here are several examples of variable declarations of various types. Note that some include an initialization.
int a, b, c; // declares three ints, a, b, and c.
int d = 3, e, f = 5; // declares three more ints, initializing
// d and f.
byte z = 22; // initializes z.
double pi = 3.14159; // declares an approximation of pi.
char x = ‘x’; // the variable x has the value ‘x’.
Dynamic Initialization
Java allows variables to be initialized dynamically, using any expression valid at the time the variable is declared. For example, here is a short program that computes the length of the hypotenuse of a right triangle given the lengths of its two opposing sides:
// Demonstrate dynamic initialization.
class DynInit {
public static void main(String args[]) {
double a = 3.0, b = 4.0;
// c is dynamically initialized
double c = Math.sqrt(a * a + b * b);
System.out.println(“Hypotenuse is ” + c);
}
}
Here, three local variables a, b,and c are declared. The first two, a and b, are initialized by constants. However, c is initialized dynamically to the length of the hypotenuse. The program uses another of Java’s built-in methods, sqrt( ), which is a member of the Math class, to compute the square root of its argument. The key point here is that the initialization expression may use any element valid at the time of the initialization, including calls to methods, other variables, or literals.
The Scope and Lifetime of Variables
Java allows variables to be declared within any block. A block is begun with an opening curly brace and ended by a closing curly brace. A block defines a scope. Thus, each time you start a new block, you are creating a new scope. A scope determines what objects are visible to other parts of your program. It also determines the lifetime of those objects. The scope defined by a method begins with its opening curly brace. However, if that method has parameters, they too are included within the method’s scope. Variables declared inside a scope are not visible that is, accessible to code that is defined outside that scope. Thus, when you declare a variable within a scope, you are localizing that variable and protecting it from unauthorized access and/or modification. Indeed, the scope rules provide the foundation for encapsulation. Scopes can be nested. For example, each time you create a block of code, you are creating a new, nested scope. When this occurs, the outer scope encloses the inner scope. This means that objects declared in the outer scope will be visible to code within the inner scope. However, the reverse is not true. Objects declared within the inner scope will not be visible outside it. To understand the effect of nested scopes, consider the following program:
// Demonstrate block scope.
class Scope {
public static void main(String args[]) {
int x; // known to all code within main
x = 10;
if(x == 10) { // start new scope
int y = 20; // known only to this block
// x and y both known here.
System.out.println(“x and y: ” + x + ” ” + y);
x = y * 2;
}
// y = 100; // Error! y not known here
// x is still known here.
System.out.println(“x is ” + x);
}
}
The variable x is declared at the start of main( )’s scope and is accessible to all subsequent code within main( ). Within the if block, y is declared. Since a block defines a scope, y is only visible to other code within its block. This is why outside of its block, the line y = 100; is commented out. If you remove the leading comment symbol, a compile-time error will occur, because y is not visible outside of its block. Within the if block, x can be used because code within a block that is, a nested scope has access to variables declared by an enclosing scope. Within a block, variables can be declared at any point, but are valid only after they are declared. Thus, if you define a variable at the start of a method, it is available to all of the code within that method. For example, this fragment is invalid because count cannot be used prior to its declaration:
// This fragment is wrong!
count = 100; // oops! cannot use count before it is declared!
int count;
Variables are created when their scope is entered, and destroyed when their scope is left. This means that a variable will not hold its value once it has gone out of scope. Therefore, variables declared within a method will not hold their values between calls to that method. Also, a variable declared within a block will lose its value when the block is left. Thus, the lifetime of a variable is confined to its scope. If a variable declaration includes an initializer, then that variable will be reinitialized each time the block in which it is declared is entered. For example, consider the next program.
// Demonstrate lifetime of a variable.
class LifeTime {
public static void main(String args[]) {
int x;
for(x = 0; x < 3; x++) {
int y = -1; // y is initialized each time block is entered
System.out.println(“y is: ” + y); // this always prints -1
y = 100;
System.out.println(“y is now: ” + y);
}
}
}
The output generated by this program is shown here:
y is: -1
y is now: 100
y is: -1
y is now: 100
y is: -1
y is now: 100
As you can see, y is always reinitialized to –1 each time the inner for loop is entered. Even though it is subsequently assigned the value 100, this value is lost. Although blocks can be nested, you cannot declare a variable to have the same name as one in an outer scope. Here is an example that tries to declare two separate variables with the same name. In Java, this is illegal.
// This program will not compile
class ScopeErr {
public static void main(String args[]) {
int bar = 1;
{ // creates a new scope
int bar = 2; // Compile-time error – bar already defined!
}
}
}
Type Conversion and Casting
If the two types are compatible, then Java will perform the conversion automatically. For example, it is always possible to assign an int value to a long variable. However, not all types are compatible, and thus, not all type conversions are implicitly allowed. For instance, there is no conversion defined from double to byte. it is still possible to obtain a conversion between incompatible types. To do so, you must use a cast, which performs an explicit conversion between incompatible types.
Java’s Automatic Conversions
When one type of data is assigned to another type of variable, an automatic type conversion will take place if the following two conditions are met:
- The two types are compatible.
- The destination type is larger than the source type.
When these two conditions are met, a widening conversion takes place. For example, the int type is always large enough to hold all valid byte values, so no explicit cast statement is required. For widening conversions, the numeric types, including integer and floating-point types, are compatible with each other. However, the numeric types are not compatible with char or boolean. Also, char and boolean are not compatible with each other.
Casting Incompatible Types
Although the automatic type conversions are helpful, they will not fulfill all needs. For example, what if you want to assign an int value to a byte variable? This conversion will not be performed automatically, because a byte is smaller than an int. This kind of conversion is sometimes called a narrowing conversion, since you are explicitly making the value narrower so that it will fit into the target type. To create a conversion between two incompatible types, you must use a cast. A cast is simply an explicit type conversion. It has this general form:
(target–type) value
Here, target-type specifies the desired type to convert the specified value to. For example, the following fragment casts an int to a byte. If the integer’s value is larger than the range of a byte, it will be reduced to byte’s range.
int a;
byte b;
// …
b = (byte) a;
A different type of conversion will occur when a floating-point value is assigned to an integer type: truncation. As you know, integers do not have fractional components. Thus, when a floating-point value is assigned to an integer type, the fractional component is lost. For example, if the value 1.23 is assigned to an integer, the resulting value will simply be 1. The 0.23 will have been truncated. Of course, if the size of the whole number component is too large to fit into the target integer type, then that value will be reduced. The following program demonstrates some type conversions that require casts:
// Demonstrate casts.
class Conversion {
public static void main(String args[]) {
byte b;
int i = 257;
double d = 323.142;
System.out.println(“\nConversion of int to byte.”);
b = (byte) i;
System.out.println(“i and b ” + i + ” ” + b);
System.out.println(“\nConversion of double to int.”);
i = (int) d;
System.out.println(“d and i ” + d + ” ” + i);
System.out.println(“\nConversion of double to byte.”);
b = (byte) d;
System.out.println(“d and b ” + d + ” ” + b);
}
}
This program generates the following output:
Conversion of int to byte.
i and b 257 1
Conversion of double to int.
d and i 323.142 323
Conversion of double to byte.
d and b 323.142 67
When the value 257 is cast into a byte variable, the result is the remainder of the division of 257 by 256 (the range of a byte), which is 1 in this case. When the d is converted to an int, its fractional component is lost. When d is converted to a byte, its fractional component is lost, and the value is reduced modulo 256, which in this case is 67.
Automatic Type Promotion in Expressions
In addition to assignments, there is another place where certain type conversions may occur: in expressions. In an expression, the precision required of an intermediate value will some times exceed the range of either operand. For example, examine the following expression:
byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;
The result of the intermediate term a * b easily exceeds the range of either of its byte operands. Java automatically promotes each byte or short operand to int when evaluating an expression. This means that the sub expression a * b is performed using integers not bytes. Thus, 2,000, the result of the intermediate expression, 50 * 40, is legal even though a and b are both specified as type byte.
The Type Promotion Rules
In addition to the elevation of bytes and shorts to int, Java defines several type promotion rules that apply to expressions. They are as follows. First, all byte and short values are promoted to int. Then, if one operand is a long, the whole expression is promoted to long. If one operand is a float, the entire expression is promoted to float. If any of the operands is double, the result is double. The following program demonstrates how each value in the expression gets promoted to match the second argument to each binary operator:
class Promote {
public static void main(String args[]) {
byte b = 42;
char c = ‘a’;
short s = 1024;
int i = 50000;
float f = 5.67f;
double d = .1234;
double result = (f * b) + (i / c) – (d * s);
System.out.println((f * b) + ” + ” + (i / c) + ” – ” + (d * s));
System.out.println(“result = ” + result);
}
}
In the line from the program:
double result = (f * b) + (i / c) – (d * s);
In the first sub expression, f * b, b is promoted to a float and the result of the sub expression is float. Next, in the sub expression i / c, c is promoted to int, and the result is of type int. Then, in d * s, the value of s is promoted to double, and the type of the sub expression is double. Finally, these three intermediate values, float, int, and double, are considered. The outcome of float plus an int is a float. Then the resultant float minus the last double is promoted to double, which is the type for the final result of the expression.
Arrays
An array is a group of like-typed variables that are referred to by a common name. Arrays of any type can be created and may have one or more dimensions. A specific element in an array is accessed by its index. Arrays offer a convenient means of grouping related information.
One-Dimensional Arrays
A one-dimensional array is, essentially, a list of like-typed variables. To create an array, you first must create an array variable of the desired type. The general form of a onedimensional array declaration is
type var-name[ ];
Here, type declares the base type of the array. The base type determines the data type of each element that comprises the array. Thus, the base type for the array determines what type of data the array will hold. For example, the following declares an array named month_days with the type “array of int”:
int month_days[];
Although this declaration establishes the fact that month_days is an array variable, no array actually exists. In fact, the value of month_days is set to null, which represents an array with no value. To link month_days with an actual, physical array of integers, you must allocate one using new and assign it to month_days. new is a special operator that allocates memory.
The general form of new as it applies to one-dimensional arrays appears as follows:
array-var = new type[size];
Here, type specifies the type of data being allocated, size specifies the number of elements in the array, and array-var is the array variable that is linked to the array. That is, to use new to allocate an array, you must specify the type and number of elements to allocate. The elements in the array allocated by new will automatically be initialized to zero. This example allocates a 12-element array of integers and links them to month_days.
month_days = new int[12];
After this statement executes, month_days will refer to an array of 12 integers. Further, all elements in the array will be initialized to zero. Obtaining an array is a two-step process. First, you must declare a variable of the desired array type. Second, you must allocate the memory that will hold the array, using new, and assign it to the array variable. Thus, in Java all arrays are dynamically allocated. Once you have allocated an array, you can access a specific element in the array by specifying its index within square brackets. All array indexes start at zero. For example, this statement assigns the value 28 to the second element of month_days.
month_days[1] = 28;
The next line displays the value stored at index 3.
System.out.println(month_days[3]);
Putting together all the pieces, here is a program that creates an array of the number of days in each month.
// Demonstrate a one-dimensional array.
class Array {
public static void main(String args[]) {
int month_days[];
month_days = new int[12];
month_days[0] = 31;
month_days[1] = 28;
month_days[2] = 31;
month_days[3] = 30;
month_days[4] = 31;
month_days[5] = 30;
month_days[6] = 31;
month_days[7] = 31;
month_days[8] = 30;
month_days[9] = 31;
month_days[10] = 30;
month_days[11] = 31;
System.out.println(“April has ” + month_days[3] + ” days.”);
}
}
When you run this program, it prints the number of days in April. Java array indexes start with zero, so the number of days in April is month_days[3] or 30. It is possible to combine the declaration of the array variable with the allocation of the array itself, as shown here:
int month_days[] = new int[12];
Arrays can be initialized when they are declared. The process is much the same as that used to initialize the simple types. An array initializer is a list of comma-separated expressions surrounded by curly braces. The commas separate the values of the array elements. The array will automatically be created large enough to hold the number of elements you specify in the array initializer. There is no need to use new. For example, to store the number of days in each month, the following code creates an initialized array of integers:
// An improved version of the previous program.
class AutoArray {
public static void main(String args[]) {
int month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,
30, 31 };
System.out.println(“April has ” + month_days[3] + ” days.”);
}
}
When you run this program, you see the same output as that generated by the previous version. Java strictly checks to make sure you do not accidentally try to store or reference values outside of the range of the array. The Java run-time system will check to be sure that all array indexes are in the correct range. For example, the run-time system will check the value of each index into month_days to make sure that it is between 0 and 11 inclusive. If you try to access elements outside the range of the array negative numbers or numbers greater than the length of the array, you will cause a run-time error. Here is one more example that uses a one-dimensional array. It finds the average of a set of numbers.
// Average an array of values.
class Average {
public static void main(String args[]) {
double nums[] = {10.1, 11.2, 12.3, 13.4, 14.5};
double result = 0;
int i;
for(i=0; i<5; i++)
result = result + nums[i];
System.out.println(“Average is ” + result / 5);
}
}
Multidimensional Arrays
In Java, multidimensional arrays are actually arrays of arrays. To declare a multidimensional array variable, specify each additional index using another set of square brackets. For example, the following declares a two-dimensional array variable called twoD.
int twoD[][] = new int[4][5];
This allocates a 4 by 5 array and assigns it to twoD. Internally this matrix is implemented as an array of arrays of int. A conceptual view of a 4 by 5, two-dimensional array The following program numbers each element in the array from left to right, top to bottom, and then displays these values:
// Demonstrate a two-dimensional array.
class TwoDArray {
public static void main(String args[]) {
int twoD[][]= new int[4][5];
int i, j, k = 0;
for(i=0; i<4; i++)
for(j=0; j<5; j++) {
twoD[i][j] = k;
k++;
}
for(i=0; i<4; i++) {
for(j=0; j<5; j++)
System.out.print(twoD[i][j] + ” “);
System.out.println();
}
}
}
This program generates the following output:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
When you allocate memory for a multidimensional array, you need only specify the memory for the first leftmost dimension. You can allocate the remaining dimensions separately. For example, this following code allocates memory for the first dimension of twoD when it is declared. It allocates the second dimension manually.
int twoD[][] = new int[4][];
twoD[0] = new int[5];
twoD[1] = new int[5];
twoD[2] = new int[5];
twoD[3] = new int[5];
While there is no advantage to individually allocating the second dimension arrays in this situation, there may be in others. For example, when you allocate dimensions manually, you do not need to allocate the same number of elements for each dimension. As stated earlier, since multidimensional arrays are actually arrays of arrays, the length of each array is under your control. For example, the following program creates a twodimensional array in which the sizes of the second dimension are unequal.
// Manually allocate differing size second dimensions.
class TwoDAgain {
public static void main(String args[]) {
int twoD[][] = new int[4][];
twoD[0] = new int[1];
twoD[1] = new int[2];
twoD[2] = new int[3];
twoD[3] = new int[4];
int i, j, k = 0;
for(i=0; i<4; i++)
for(j=0; j<i+1; j++) {
twoD[i][j] = k;
k++;
}
for(i=0; i<4; i++) {
for(j=0; j<i+1; j++)
System.out.print(twoD[i][j] + ” “);
System.out.println();
}
}
}
This program generates the following output:
0
1 2
3 4 5
6 7 8 9
The use of uneven or, irregular multidimensional arrays is not recommended for most applications, because it runs contrary to what people expect to find when a multidimensional array is encountered. However, it can be used effectively in some situations. For example, if you need a very large two-dimensional array that is sparsely populated that is, one in which not all of the elements will be used, then an irregular array might be a perfect solution. It is possible to initialize multidimensional arrays. To do so, simply enclose each dimension’s initializer within its own set of curly braces. The following program creates a matrix where each element contains the product of the row and column indexes. Also notice that you can use expressions as well as literal values inside of array initializers.
// Initialize a two-dimensional array.
class Matrix {
public static void main(String args[]) {
double m[][] = {
{ 0*0, 1*0, 2*0, 3*0 },
{ 0*1, 1*1, 2*1, 3*1 },
{ 0*2, 1*2, 2*2, 3*2 },
{ 0*3, 1*3, 2*3, 3*3 }
};
int i, j;
for(i=0; i<4; i++) {
for(j=0; j<4; j++)
System.out.print(m[i][j] + ” “);
System.out.println();
}
}
}
When you run this program, you will get the following output:
0.0 0.0 0.0 0.0
0.0 1.0 2.0 3.0
0.0 2.0 4.0 6.0
0.0 3.0 6.0 9.0
As you can see, each row in the array is initialized as specified in the initialization lists. The following program creates a 3 by 4 by 5, three-dimensional array. It then loads each element with the product of its indexes. Finally, it displays these products.
// Demonstrate a three-dimensional array.
class threeDMatrix {
public static void main(String args[]) {
int threeD[][][] = new int[3][4][5];
int i, j, k;
for(i=0; i<3; i++)
for(j=0; j<4; j++)
for(k=0; k<5; k++)
threeD[i][j][k] = i * j * k;
for(i=0; i<3; i++) {
for(j=0; j<4; j++) {
for(k=0; k<5; k++)
System.out.print(threeD[i][j][k] + ” “);
System.out.println();
}
System.out.println();
}
}
}
This program generates the following output:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 2 3 4
0 2 4 6 8
0 3 6 9 12
0 0 0 0 0
0 2 4 6 8
0 4 8 12 16
0 6 12 18 24
Alternative Array Declaration Syntax
There is a second form that may be used to declare an array:
type[ ] var-name;
Here, the square brackets follow the type specifier, and not the name of the array variable. For example, the following two declarations are equivalent:
int al[] = new int[3];
int[] a2 = new int[3];
The following declarations are also equivalent:
char twod1[][] = new char[3][4];
char[][] twod2 = new char[3][4];
This alternative declaration form is included as a convenience, and is also useful when specifying an array as a return type for a method.