Chapter 3

Ace your homework & exams now with Quizwiz!

multidimensional arrays

In Java, multidimensional arrays are actually arrays of arrays. These, as you might expect, look and act like regular multidimensional arrays. However, as you will see, there are a couple of subtle differences. 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. Conceptually, this array will look like the one shown in Figure 3-1. 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 two-dimensional 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 may not be appropriate for many applications, because it runs contrary to what people expect to find when a multidimensional array is encountered. However, irregular arrays 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 initialise multidimensional arrays. To do so, simply enclose each dimension's initialiser 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 initialisers. // 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 initialised as specified in the initialisation lists. Let's look at one more example that uses a multidimensional array. 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

Character literals

A literal character is represented inside a pair of single quotes, such as 'a' or '@'. the backward slash (and other methods) can be used for characters impossible to enter directly.

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 one-dimensional array declaration is type var-name[ ]; Here, type declares the element type (also called the base type) of the array. The element type determines the data type of each element that comprises the array. Thus, the element 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[]; Chapter 3 Data Types, Variables, and Arrays 51 Let's look closely at the type promotions that occur in this line from the program: Part I 52 PART I The Java Language Although this declaration establishes the fact that month_days is an array variable, no array actually exists. 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. You will look more closely at new in a later chapter, but you need to use it now to allocate memory for arrays. 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 (for numeric types), false (for boolean), or null (for reference types, which are described in a later chapter). 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. Let's review: 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. If the concept of dynamic allocation is unfamiliar to you, don't worry. It willbe described at length later in this book. 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; Chapter 3 Data Types, Variables, and Arrays 53 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. As mentioned, 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]; This is the way that you will normally see it done in professionally written Java programs. 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; Part I 54 PART I The Java Language for(i=0; i<5; i++) result = result + nums[i]; System.out.println("Average is " + result / 5); } }

Why is Java a strongly typed language?

Java checks for type compatibility of the code before running it.

Primitive data types

Represents single values (not complex objects). Primitive types are not object orientated - this is due to performance. All data types have a strictly defined range (e.g. an int is 32 bits)

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 initialiser. All variables have a scope, which defines their visibility and a lifetime.

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 offers convenience when declaring several arrays at the same time. For example, int[] nums, nums2, nums3; // create three arrays creates three array variables of type int. It is the same as writing int nums[], nums2[], nums3[]; // create three arrays The alternative declaration form is also useful when specifying an array as a return type for a method. Both forms are used in this book.

Notes

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 initialiser, then that variable will be reinitialised each time the block in which it is declared is entered.

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, there are no automatic conversions from the numeric types to char or boolean. Also, char and boolean are not compatible with each other. As mentioned earlier, Java also performs an automatic type conversion when storing a literal integer constant into variables of type byte, short, long, or char.

Blocks 47

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. Conversely, if you declare a variable at the end of a block, it is effectively useless, because no code will have access to it.

ASCII values for a char

65 is A (capital) 97 is a (lowercase)

Integers

All integer types are signed, positive and negative. Java does not support unsigned positive only integers. byte - 8 bit type with a range from -128 to 127. byte is useful when working with a stream of data from a network or file. short - 16 bit type with a range from -32,768 to 32,767. int - 32 bit type with a range from -2,147,483,648 to 2,147,483,647. int is commonly employed in control loops and index arrays. byte and short values are promoted to int when an expression is evaluated. long - 64 bit type with a large range. Useful when the numbers in question are too big for int.

Characters

All of javas characters are represented with Unicode (represents all the characters found in all human languages). When java was created, Unicode required 16 bits, so char is a 16 bit type. The range of char is 0 to 65,536 (there are no negative char values). Although char uses Unicode characters, it can also be used as an. integer type to perform arithmetic operations. It is also an integer type, but holds a category of its own.

Floating point types

Also known as real numbers and are used when evaluating expressions that require fractional precision, e.g. square roots, sin/cos float - specifies a single precision value that uses 32 bits of storage. Single precision is faster on some processors and takes half as much space as double precision. However, it will become imprecise when the values are very large/small. float is useful when you need a fractional component that does not require a large degree of precision, like dollars and cents. double - uses double precision and is 64 bits. Double is faster on some modern processors, and sine and cosine both need double.

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.

Declaring a variable

Basic form is: type identifier [ = value] [, identifier[= value]...]; identifier is the name of the variable. you initialise the variable by specifying an equal sign and value.

Floating point literals

Can be represented in two ways: 1. standard notation - consists of a whole number followed by a decimal point followed by a fractional component, e.g. 2.0 or 3.1459 or 0.6667. 2. scientific notation - consists of a standard notation, a floating point number and a suffix that specifies a power of 10 which the number is to be multiplied by. The exponent is indicated by an E or e followed by a decimal number (positive or negative). Example is 6.022E23 or 2e+100 or 314159E-05. Floating point literals in Java default to the double precision. Therefore, to specify a float literal you have to append an F or f to the constant. For hexadecimal floating point literals, you have to do it in the form of a scientific notation, with the use of either P or p, for example 0x12.2P2. The 'P' in that number is referred to as a binary exponent, and indicates the power of two at which the number is multiplied by. Underscores can also be used in floating point literals, and serve to make reading large floating point literals easier, and when the literal is compiled, the underscores are discarded. Underscores can only be used to separate digits, not at the beginning or end of a literal.

Automatic type promotion in expressions

In addition to assignments, there is another place where certain type conversions may occur: in expressions. To see why, consider the following. In an expression, the precision required of an intermediate value will sometimes 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. To handle this kind of problem, Java automatically promotes each byte, short, or char operand to int when evaluating an expression. This means that the subexpression 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. As useful as the automatic promotions are, they can cause confusing compile-time errors. For example, this seemingly correct code causes a problem: byte b = 50; b = b * 2; // Error! Cannot assign an int to a byte! The code is attempting to store 50 * 2, a perfectly valid byte value, back into a byte variable. However, because the operands were automatically promoted to int when the expression was evaluated, the result has also been promoted to int. Thus, the result of the expression is now of type int, which cannot be assigned to a byte without the use of a cast. This is true even if, as in this particular case, the value being assigned would still fit in the target type. In cases where you understand the consequences of overflow, you should use an explicit cast, such as byte b = 50; b = (byte)(b * 2); which yields the correct value of 100.

Boolean literals

In java, the boolean literals can only be assigned to variables declared as boolean or used in expressions with boolean operators.

Integer literals

Integers can hold base 10,8 and 16 values (decimal, octal and hexadecimal respectively). Octal values are denoted by a leading 0, and the range is 0 to 7. Hexadecimal values are denoted by a leading zero x (either 0x or 0X), and the range is 0 to 15, with 10 to 15 being represented by a to f). Integer literals can create an int value, and for byte or long as well if the value is within the range of the target type. To specify a long literal, you have to tell the compiler that the literal value is of the type long. You do this by appending an upper or lower case l to the literal, e.g. 0x7ffffffffffffffL. An integer can also be assigned to char as long as it is within range. You can also specify integer literals using binary, and you do this by prefixing it with 0b or 0B. For example, you could write: int x = 0b1010; The use of underscores when setting a number value acts to separate digits, for example: int x = 123_456_789; would output the number 123,456,789. This is useful when encoding ID numbers, telephone numbers etc.

Scope

Java allows variables to be declared within any block. A block begins and closes with curly braces. A block defines a scope, and a scope determines what objects are visible to other parts of your program and the lifetime of those objects. In java, the two main scopes are those defined by a class and a method. The scope defined by a method begins with its opening curly braces. However, if that method has parameters, they too are included within the method's scope. Variables declared inside a scope are not visible (accessible) to code that is defined outside that scope. Thus, when you declare a variable within a scope, you are localising that variable and protecting it from unauthorised access and/or modification. The scope rules provide the foundation for encapsulation. Scopes can be nested. Each time you create a block of code, you are creating a new, nested scope. When this happens, the outer scope encloses the inner scope, which 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.

Why does java not have pointers?

Java cannot allow pointers, because doing so would allow Java programs to breach the firewall between the Java execution environment and the host computer. (Remember, a pointer can be given any address in memory—even addresses that might be outside the Java run-time system.) Since C/C++ make extensive use of pointers, you might be thinking that their loss is a significant disadvantage to Java. However, this is not true. Java is designed in such a way that as long as you stay within the confines of the execution environment, you will never need to use a pointer, nor would there be any benefit in using one.

The type promotion rules

Java defines several type promotion rules that apply to expressions. They are as follows: First, all byte, short, and char values are promoted to int, as just described. 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 are 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); } } Let's look closely at the type promotions that occur in this line from the program: double result = (f * b) + (i / c) - (d * s); In the first subexpression, f * b, b is promoted to a float and the result of the subexpression is float. Next, in the subexpression 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 subexpression 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.

String literals

String literals are specified by enclosing a sequence of characters between a pair of double quotes, such as "Hello World" or "\"This is in quotes\"". The escape notations for character literals work the same here. IMPORTANT: Java strings must begin and end on the same line, there is no continuation escape sequence as there is in other languages.

String notes

The String type is used to declare string variables. You can also declare arrays of strings. A quoted string constant can be assigned to a String variable. A variable of type String can be assigned to another variable of type String. You can use an object of type String as an argument to println( ). For example, consider the following fragment: String str = "this is a test"; System.out.println(str); Here, str is an object of type String. It is assigned the string "this is a test". This string is displayed by the println( ) statement. As you will see later, String objects have many special features and attributes that make them quite powerful and easy to use. However, for the next few chapters, you will be using them only in their simplest form.

Escape sequences

\n means new line \ddd means octal character (ddd) \uxxxx means Hexidecimal Unicode character (xxxx) \' means single quote \" means double quote \\ means backslash \r means carriage return \f means form feed \t means tab \b means backspace

Boolean(Primitive type):

boolean - represents true/false values

Booleans

boolean is the primitive type for logical values. It returns true or false. A value of a boolean variable is sufficient by itself to control an if statement.

Integers (Primitive type):

byte, short, int and long - whole valued numbers

Dynamic initialisation

example: double a = 3.0, b= 4.0; double c = Math.sqrt(a * a + b * b); The initialisation expression may use any element valid at any time of the initialisation, including calls to methods, other variables or literals

Floating point numbers (Primitive type):

float and double - number with fractional precision (decimal places)

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 Chapter 3 Data Types, Variables, and Arrays 49 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 modulo (the remainder of an integer division by the) 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 modulo the target type's range.

Characters (Primitive type):

char - symbols in a character set, like letters/numbers


Related study sets

The Notorious Jumping Frog of Calaveras County review

View Set

US History: Reasons for Expansionism and the Story of Hawaii Notes

View Set

Chapter 15 - give me liberty study guide/chronological (copied)

View Set