| ## Java 1.1 Unleashed # - 3 - Java Language Fundamentals by Michael Morrison IN THIS CHAPTER Hello, World! Tokens Data Types Casting Types Blocks and Scope Arrays Strings Java is an object-oriented language. This means that the language is based on the concept of an object. Although a knowledge of object-oriented programming is necessary to put Java to practical use, it isn't required to understand the fundamentals of the Java language. This chapter focuses on the language and leaves the object-oriented details of Java for Chapter 5, "Classes, Packages, and Interfaces." If you already have some experience with another object-oriented language such as C++ or Smalltalk, much of Java will be familiar territory. In fact, you can almost consider Java a new, revamped C++. Because Java evolved from C++, many of the similarities and differences between Java and C++ will be highlighted throughout the next few chapters. This chapter covers the essentials of the Java language, including a few sample programs to help you hit the ground running. ## Hello, World! The best way to learn a programming language is to jump right in and see how a real program works. In keeping with a traditional introductory programming example, your first program is a Java version of the classic "Hello, World!" program. List- ing 3.1 contains the source code for the `HelloWorld` class, which also is located on the CD-ROM that accompanies this book in the file `HelloWorld.java`. #### Listing 3.1. The HelloWorld class.
    class HelloWorld {
      public static void main(String args[]) {
        System.out.println("Hello, World!");
      }

    }
After compiling the program with the Java compiler (`javac`), you are ready to run it in the Java interpreter. The Java compiler places the executable output in a file called `HelloWorld.class`. This naming convention might seem strange considering the fact that most programming languages use the `.EXE` file extension for executables. Not so in Java! Following the object- oriented nature of Java, all Java programs are stored as Java classes that are created and executed as objects in the Java runtime environment. To run the `HelloWorld` program, type java HelloWorld at the command prompt. As you may have guessed, the program responds by displaying `Hello, World!` on your screen. Congratulations! You just wrote and tested your first Java program! Obviously, `HelloWorld` is a very minimal Java program. Even so, there's still a lot happening in those few lines of code. To fully understand what is happening, let's examine the program line by line. First, you must understand that Java relies heavily on classes. In fact, the first statement of `HelloWorld` reminds you that `HelloWorld` is a class, not just a program. Furthermore, by looking at the `class` statement in its entirety, you can see that the name of the class is defined as `HelloWorld`. This name is used by the Java compiler as the name of the executable output class. The Java compiler creates an executable class file for each class defined in a Java source file. If there is more than one class defined in a `.java` file, the Java compiler stores each class in a separate `.class` file. The `HelloWorld` class contains one method, or member function. For now, you can think of this function as a normal procedural function that happens to be linked to the class. The details of methods are covered in Chapter 5, "Classes, Packages, and Interfaces." The single method in the `HelloWorld` class is called `main()` and should be familiar if you have used C or C++. The `main()` method is where execution begins when the class is executed in the Java interpreter. The `main()` method is defined as being `public static` with a `void` return type. `public` means that the method can be called from anywhere inside or outside the class. `static` means that the method is the same for all instances of the class. The `void` return type means that `main()` does not return a value. The `main()` method is defined as taking a single parameter, `String` `args[]`. `args` is an array of `String` objects that represent command-line arguments passed to the class at execution. Because `HelloWorld` doesn't use any command-line arguments, you can ignore the `args` parameter. You learn a little more about strings later in this chapter. The `main()` method is called when the `HelloWorld` class is executed. `main()` consists of a single statement that prints the message `Hello, World!` to the standard output stream, as follows: `System.out.println("Hello, World!");` This statement may look a little confusing at first because of the nested objects. To help make things clearer, examine the statement from right to left. First, notice that the statement ends in a semicolon, which is standard Java syntax borrowed from C/C++. Moving to the left, you see that the `"Hello, World!"` string is in parentheses, which means that it is a parameter to a function call. The method being called is actually the `println()` method of the `out` object. The `println()` method is similar to the `printf()` method in C, except that it automatically appends a newline character (`\n`) at the end of the string. The `out` object is a member variable of the `System` object that represents the standard output stream. Finally, the `System` object is a global object in the Java environment that encapsulates system functionality. That pretty well covers the `HelloWorld` class--your first Java program. If you got a little lost in the explanation of the `HelloWorld` class, don't be too concerned. `HelloWorld` was presented with no previous explanation of the Java language and was only meant to get your feet wet with Java code. The rest of this chapter focuses on a more structured discussion of the fundamentals of the Java language. ## Tokens When you submit a Java program to the Java compiler, the compiler parses the text and extracts individual tokens. A token is the smallest element of a program that is meaningful to the compiler. (Actually, this definition is true for all compilers, not just the Java compiler.) These tokens define the structure of the Java language. All the tokens that comprise Java are known as the Java token set. Java tokens can be broken into five categories: identifiers, keywords, literals, operators, and separators. The Java compiler also recognizes and subsequently removes comments and whitespaces. The Java compiler removes all comments and whitespaces while tokenizing the source file. The resulting tokens are then compiled into machine-independent Java bytecode capable of being run from within an interpreted Java environment. The bytecode conforms to the hypothetical Java virtual machine, which abstracts processor differences into a single virtual processor. For more information on the Java virtual machine, check out Chapter 33, "Java Under the Hood: Inside the Virtual Machine." Keep in mind that an interpreted Java environment can be either the Java command-line interpreter or a Java-capable browser. ### Identifiers Identifiers are tokens that represent names. These names can be assigned to variables, methods, and classes to uniquely identify them for the compiler and give them meaningful names for the programmer. `HelloWorld` is an identifier that assigns the name `HelloWorld` to the class residing in the `HelloWorld.java` source file developed earlier. Although you can be creative in naming identifiers in Java, there are some limitations. All Java identifiers are case sensitive and must begin with a letter, an underscore ( _ ), or a dollar sign (`$`). Letters include both uppercase and lowercase letters. Subsequent identifier characters can include the numbers `0` to `9`. The only other limitation to identifier names is that the Java keywords, which are listed in the next section, cannot be used. Table 3.1 contains a list of valid and invalid identifier names. #### Table 3.1. Valid and invalid Java identifiers.
Valid | Invalid
`HelloWorld` | `Hello World` (uses a space)
`Hi_Mom` | `Hi Mom!` (uses a space and punctuation mark)
`heyDude3` | `3heyDude` (begins with a numeral)
`tall` | `short` (this is a Java keyword)
`poundage` | `#age` (does not begin with a letter)
In addition to the mentioned restrictions in naming Java identifiers, you should follow a few stylistic rules to make your Java programming easier and more consistent. It is standard Java practice to name multiple-word identifiers in lowercase except for the beginning letter of words in the middle of the name. For example, the variable `toughGuy` is in correct Java style; the variables `toughguy`, `ToughGuy`, and `TOUGHGUY` are all in violation of this style rule. The rule isn't etched in stone--it's just a good rule to follow because most other Java code you run into follows this style. Another more critical naming issue regards the use of underscore and dollar-sign characters at the beginning of identifier names. Using either of these characters at the beginning of identifier names is a little risky because many C libraries use the same naming convention for libraries that can be imported into your Java code. To eliminate the potential problem of name-clashing in these instances, it's better to stay away from the underscore and dollar-sign characters at the beginning of your identifier names. A good use of the underscore character is to use it to separate words where you normally would use a space (`Hi_Mom`). NOTE: With Java 1.1, the style conventions in naming identifiers has become significantly more important. JavaBeans, which is the new component technology in Java 1.1, depends in part on the standard identifier-naming conventions if it is to function properly. You learn more about JavaBeans and the naming conventions it relies on in Part VIII, "Java Archives and JavaBeans." ### Keywords Keywords are predefined identifiers reserved by Java for a specific purpose and are used only in a limited, specified manner. Java has a richer set of keywords than C or C++, so if you are learning Java with a C/C++ background, be sure to pay attention to the Java keywords. The following keywords are reserved for Java:
`abstract` | `double` | `int` | `super`
`boolean` | `else` | `interface` | `switch`
`break` | `extends` | `long` | `synchronized`
`byte` | `false` | `native` | `this`
`byvalue` | `final` | `new` | `threadsafe`
`case` | `finally` | `null` | `throw`
`catch` | `float` | `package` | `transient`
`char` | `for` | `private` | `true`
`class` | `goto` | `protected` | `try`
`const` | `if` | `public` | `void`
`continue` | `implements` | `return` | `while`
`default` | `import` | `short` |
`do` | `instanceof` | `static` |
### Literals Program elements used in an invariant manner are called literals, or constants. Literals can be numbers, characters, or strings. Numeric literals include integers, floating-point numbers, and booleans. Booleans are considered numeric because of the C influence on Java. In C, the boolean values for `true` and `false` are represented by `1` and `0`. Character literals always refer to a single Unicode character. Strings, which contain multiple characters, are still considered literals even though they are implemented in Java as objects. NOTE: If you aren't familiar with the Unicode character set, you should know that it is a 16-bit character set that replaces the ASCII character set. Because it is a 16-bit character set, there are enough entries to represent many symbols and characters from other languages. Unicode is quickly becoming the standard for modern operating systems. #### Integer Literals Integer literals are the primary literals used in Java programming. They come in a few different formats: decimal, hexadecimal, and octal. These formats correspond to the base of the number system used by the literal. Decimal (base 10) literals appear as ordinary numbers with no special notation. Hexadecimal numbers (base 16) appear with a leading `0x` or `0X`, similar to the way they do in C/C++. Octal (base 8) numbers appear with a leading `0` in front of the digits. For example, an integer literal for the decimal number 12 is represented in Java as `12` in decimal, `0xC` in hexadecimal, and `014` in octal. Integer literals default to being stored in the `int` type, which is a signed 32-bit value. If you are working with very large numbers, you can force an integer literal to be stored in the `long` type by appending an `l` or `L` to the end of the number, as in `79L`. The `long` type is a signed 64-bit value. #### Floating-Point Literals Floating-point literals represent decimal numbers with fractional parts, such as `3.142`. They can be expressed in either standard or scientific notation, meaning that the number `563.84` also can be expressed as `5.6384e2`. Unlike integer literals, floating-point literals default to the `double` type, which is a 64-bit value. You have the option of using the smaller 32-bit `float` type if you know the full 64 bits are not required. You do this by appending an `f` or `F` to the end of the number, as in `5.6384e2f`. If you are a stickler for details, you also can explicitly state that you want a `double` type as the storage unit for your literal, as in `3.142d`. But because the default storage for floating-point numbers is `double` already, this addition isn't necessary. #### Boolean Literals Boolean literals are certainly welcome if you are coming from the world of C/C++. In C, there is no `boolean` type, and therefore no boolean literals. The boolean values `true` and `false` are represented by the integer values `1` and `0`. Java fixes this problem by providing a `boolean` type with two possible states: `true` and `false`. Not surprisingly, these states are represented in the Java language by the keywords `true` and `false`. Boolean literals are used in Java programming about as often as integer literals because they are present in almost every type of control structure. Any time you have to represent a condition or state with two possible values, a `boolean` is what you want. You learn a little more about the `boolean` type later in this chapter. For now, just remember the two boolean literal values: `true` and `false`. #### Character Literals and Special Characters Character literals represent a single Unicode character and appear within a pair of single quotation marks. Similar to C/C++, special characters (control characters and characters that cannot be printed) are represented by a backslash (`\`) followed by the character code. A good example of a special character is `\n`, which forces the output to a new line when printed. Table 3.2 shows the special characters supported by Java. #### Table 3.2. Special characters supported by Java.
Description | Representation
Backslash | `\\`
Continuation | `\`
Backspace | `\b`
Carriage return | `\r`
Form feed | `\f`
Horizontal tab | `\t`
Newline | `\n`
Single quote | `\'`
Double quote | `\"`
Unicode character | `\u`dddd
Octal character | `\`ddd
An example of a Unicode character literal is `\u0048`, which is a hexadecimal representation of the character H. This same character is represented in octal as `\110`. NOTE: To find out more information about the Unicode character set, check out the Unicode home page at this URL: `http://www.unicode.org` #### String Literals String literals represent multiple characters and appear within a pair of double quotation marks. Unlike all the other literals discussed in this chapter, string literals are implemented in Java by the `String` class. This arrangement is very different from the C/C++ representation of strings as an array of characters. When Java encounters a string literal, it creates an instance of the `String` class and sets its state to the characters appearing within the double quotation marks. From a usage perspective, the fact that Java implements strings as objects is relatively unimportant. However, it is worth mentioning at this point because it is a reminder that Java is very object oriented in nature--much more so than C++, which is widely considered the current object-oriented programming standard. ### Operators Operators, also known as operands, specify an evaluation or computation to be performed on a data object or objects. These operands can be literals, variables, or function return types. The operators supported by Java follow:
`+` | `-` | `*` | `/` | `%` | `&` | `|`
`^` | `~` | `&&` | `||` | `!` | `<` | `>`
`<=` | `>=` | `<<` | `>>` | `>>>` | `=` | `?`
`++` | `--` | `==` | `+=` | `-=` | `*=` | `/=`
`%=` | `&=` | `|=` | `^=` | `!=` | `<<=` | `>>=`
`>>>=` | . | `[` | ] | ( | ) |
Just seeing these operators probably doesn't help you a lot in determining how to use them. Don't worry--you'll learn a lot more about operators and how they are used in the next chapter, "Expressions, Operators, and Control Structures." ### Separators Separators are used to inform the Java compiler of how things are grouped in the code. For example, items in a list are separated by commas much like lists of items in a sentence. Java separators go far beyond commas, however, as you discover in the next chapter. The separators supported by Java follow:
`{` | `}` | `;` | `,` | `:`
### Comments and Whitespaces Earlier in this chapter, you learned that comments and whitespaces are removed by the Java compiler during the tokenization of the source code. You may be wondering, "What qualifies as whitespace and how are comments supported?" First, whitespace consists of spaces, tabs, and linefeeds. All occurrences of spaces, tabs, and linefeeds are removed by the Java compiler, as are comments. Comments can be defined in three different ways, as shown in Table 3.3. #### Table 3.3. Types of comments supported by Java.
Type | Usage
`/*` comment `*/` | All characters between `/*` and `*/` are ignored.
`//` comment | All characters after the `//` up to the end of the line are ignored.
`/**` comment`*/` | Same as `/* */`, except that the comment can be used with the `javadoc` tool to create automatic documentation.
The first type of comment (`/*` comment`*/`) should be familiar if you have programmed in C. All characters inside the `/*` and `*/` comment delimiters are ignored by the compiler. The second type of comment (`//` comment) should also be familiar if you have used C++. All characters appearing after the `//` comment delimiter up to the end of the line are ignored by the compiler. These two comment types are borrowed from C and C++. The final comment type (`/**` comment`*/`) works in the same fashion as the C-style comment type, with the additional benefit that it can be used with the Java documentation generator tool, `javadoc`, to create automatic documentation from the source code. The `javadoc` tool is covered in Chapter 29, "Documenting Your Code." Following are a few examples using the various types of comments:
    /* This is a C style comment. */
    // This is a C++ style comment.
    /** This is a javadoc style comment. */
## Data Types One of the fundamental concepts of any programming language is data types. Data types define the storage methods available for representing information, along with how the information is interpreted. Data types are linked tightly to the storage of variables in memory because the data type of a variable determines how the compiler interprets the contents of the memory. You already have received a little taste of data types in the discussion of literal types. To create a variable in memory, you must declare it by providing the type of the variable as well as an identifier that uniquely identifies the variable. The syntax of the Java declaration statement for variables follows:
    Type Identifier [, Identifier];
The declaration statement tells the compiler to set aside memory for a variable of type Type with the name Identifier. The optional bracketed Identifier indicates that you can make multiple declarations of the same type by separating them with commas. Finally, as in all Java statements, the declaration statement ends with a semicolon. Java data types can be divided into two categories: simple and composite. Simple data types are core types not derived from any other types. Integer, floating-point, boolean, and character types are all simple types. Composite types, on the other hand, are based on simple types and include strings, arrays, and both classes and interfaces in general. You learn about arrays later in this chapter. Classes and interfaces are covered in Chapter 5, "Classes, Packages, and Interfaces." ### Integer Data Types Integer data types are used to represent signed integer numbers. There are four integer types: `byte`, `short`, `int`, and `long`. Each of these types takes up a different amount of space in memory, as shown in Table 3.4. #### Table 3.4. Java integer types.
Type | Size
`byte` | 8 bits
`short` | 16 bits
`int` | 32 bits
`long` | 64 bits
To declare variables using the integer types, use the declaration syntax mentioned previously with the desired type. Following are some examples of declaring integer variables:
    int i;
    short rocketFuel;
    long angle, magnitude;

    byte red, green, blue;
### Floating-Point Data Types Floating-point data types are used to represent numbers with fractional parts. There are two floating point types: `float` and `double`. The `float` type reserves storage for a 32-bit single-precision number; the `double` type reserves storage for a 64-bit double-precision number. Declaring floating-point variables is very similar to declaring integer variables. Following are some examples of floating-point variable declarations:
    float temperature;

    double windSpeed, barometricPressure;
### Boolean Data Type The boolean data type (`boolean`) is used to store values with one of two states: `true` or `false`. You can think of the `boolean` type as a 1-bit integer value (because 1 bit can have only two possible values: `1` or `0`). However, instead of using `1` and `0`, you use the Java keywords `true` and `false`. `true` and `false` aren't just conveniences in Java; they are actually the only legal boolean values. This means that you can't interchangeably use booleans and integers as you can in C/C++. To declare a boolean value, just use the `boolean` type declaration:
    boolean gameOver;
### Character Data Type The character data type `(char)` is used to store single Unicode characters. Because the Unicode character set is composed of 16-bit values, the `char` data type is stored as a 16-bit unsigned integer. You create variables of type `char` as follows:
    char firstInitial, lastInitial;
Remember that the `char` type is useful only for storing single characters. If you come from a C/C++ background, you may be tempted to fashion a string by creating an array of `char`s. In Java, this isn't necessary because the `String` class takes care of handling strings. This doesn't mean that you should never create arrays of characters, it just means that you shouldn't use a character array when you really want a string. C and C++ do not distinguish between character arrays and strings, but Java does. ## Casting Types Inevitably, there will be times when you have to convert from one data type to another. The process of converting one data type to another is called casting. Casting is often necessary when a function returns a type different than the type you need to perform an operation. For example, the `read()` member function of the standard input stream (`System.in`) returns an `int`. You must cast the returned `int` type to a `char` type before storing it, as in the following:
    char c = (char)System.in.read();
The cast is performed by placing the desired type in parentheses to the left of the value to be converted. The `System.in.read()` function call returns an `int` value, which then is cast to a `char` value because of the `(char)` cast. The resulting `char` value is then stored in the `char` variable `c`. CAUTION: The storage size of the types you are attempting to cast is very important. Not all types can be safely cast to other types. To understand this, consider the outcome of casting a `long` to an `int`. A `long` is a 64-bit value and an `int` is a 32-bit value. When casting a `long` to an `int`, the compiler chops off the upper 32 bits of the `long` value so that it will fit into the 32-bit `int`. If the upper 32 bits of the `long` contain any useful information, that information is lost and the number changes as a result of the cast. Information loss can also occur when you cast between different fundamental types, such as between integer and floating-point numbers. For example, casting a `double` to a `long` results in the loss of the fractional information, even though both numbers are 64-bit values. When casting, the destination type should always be equal to or larger in size than the source type. Furthermore, you should pay close attention to casting across fundamental types, such as from floating-point to integer types. Table 3.5 lists the casts that are guaranteed to result in no loss of information. #### Table 3.5. Casts that result in no loss of information.
From Type | To Type
`byte` | `short`, `char`, `int`, `long`, `float`, `double`
`short` | `int`, `long`, `float`, `double`
`char` | `int`, `long`, `float`, `double`
`int` | `long`, `float`, `double`
`long` | `float`, `double`
`float` | `double`
## Blocks and Scope In Java, source code is divided into parts separated by opening and closing curly braces: `{` and `}`. Everything between curly braces is considered a block and exists more or less independently of everything outside the braces. Blocks aren't important just from a logical sense--they are required as part of the syntax of the Java language. If you don't use braces, the compiler has trouble determining where one section of code ends and the next section begins. And from a purely aesthetic viewpoint, it is very difficult for someone else reading your code to understand what is going on if you don't use the braces. For that matter, it isn't very easy for you to understand your own code without the braces! Braces are used to group related statements together. You can think of everything between matching braces as being executed as one statement. In fact, from an outer block, that's exactly what an inner block appears like: a single statement. But what's a block? A block is simply a section of code. Blocks are organized in a hierarchical fashion, meaning that code can be divided into individual blocks nested under other blocks. One block can contain one or more nested subblocks. It is standard Java programming style to identify different blocks with indentation. Every time you enter a new block, you should indent your source code by a number of spaces--preferably two. When you leave a block, you should move back, or deindent, two spaces. This is a fairly established convention in many programming languages. However, indentation is just a style issue and is not technically part of the language. The compiler produces identical output even if you don't indent anything. Indentation is used for the programmer, not the compiler; it simply makes the code easier to follow and understand. Following is an example of the proper indentation of blocks in Java:
    for (int i = 0; i < 5; i++) {
      if (i < 3) {
        System.out.println(i);
      }

    }
Following is the same code without any block indentations:
    for (int i = 0; i < 5; i++) {
    if (i < 3) {
    System.out.println(i);
    }
    }
The first bit of code clearly shows the breakdown of program flow through the use of indentation; it is obvious that the `if` statement is nested within the `for` loop. The second bit of code, on the other hand, provides no visual clues about the relationship between the blocks of code. Don't worry if you don't know anything about `if` statements and `for` loops; you'll learn plenty about them in the next chapter, "Expressions, Operators, and Control Structures." The concept of scope is tightly linked to blocks and is very important when you are working with variables in Java. Scope refers to how sections of a program (blocks) affect the lifetime of variables. Every variable declared in a program has an associated scope, meaning that the variable is used only in that particular part of the program. Scope is determined by blocks. To better understand blocks, take a look again at the `HelloWorld` class in Listing 3.1, earlier in this chapter. The `HelloWorld` class is composed of two blocks. The outer block of the program is the block defining the `HelloWorld` class:
    class HelloWorld {
    ...

    }
Class blocks are very important in Java. Almost everything of interest is either a class itself or belongs to a class. For example, methods are defined inside the classes to which they belong. Both syntactically and logically, everything in Java takes place inside a class. Getting back to `HelloWorld`, the inner block defines the code within the `main()` method, as follows:
    public static void main (String args[]) {
    ...

      }
The inner block is considered to be nested within the outer block of the program. Any variables defined in the inner block are local to that block and are not visible to the outer block; the scope of the variables is defined as the inner block. To get an even better idea of what's behind the usage of scope and blocks, take a look at the `HowdyWorld` class in Listing 3.2. #### Listing 3.2. The HowdyWorld class.
    class HowdyWorld {
      public static void main (String args[]) {
        int i;
        printMessage();
      }
      public static void printMessage () {
        int j;
        System.out.println("Howdy, World!");
      }

    }
The `HowdyWorld` class contains two methods: `main()` and `printMessage()`. `main()` should be familiar to you from the `HelloWorld` class, except that in this case, it declares an integer variable `i` and calls the `printMessage()` method. `printMessage()` is a new method that declares an integer variable `j` and prints the message `Howdy, World!` to the standard output stream, much like the `main()` method does in `HelloWorld`. You've probably figured out already that `HowdyWorld` results in basically the same output as `HelloWorld` because the call to `printMessage()` results in a single text message being displayed. What you may not see right off is the scope of the integers defined in each method. The integer `i` defined in `main()` has a scope limited to the body of the `main()` method. The body of `main()` is defined by the curly braces around the method (the method block). Similarly, the integer `j` has a scope limited to the body of the `printMessage()` method. The importance of the scope of these two variables is that the variables aren't visible beyond their respective scopes; the `HowdyWorld` class block knows nothing about the two integers. Furthermore, `main()` doesn't know anything about `j`, and `printMessage()` knows nothing about `i`. Scope becomes more important when you start nesting blocks of code within other blocks. The `GoodbyeWorld` class shown in Listing 3.3 is a good example of variables nested within different scopes. #### Listing 3.3. The GoodbyeWorld class.
    class GoodbyeWorld {
      public static void main (String args[]) {
        int i, j;
        System.out.println("Goodbye, World!");
        for (i = 0; i < 5; i++) {
          int k;
          System.out.println("Bye!");
        }
      }

    }
The integers `i` and `j` have scopes within the `main()` method body. The integer `k`, however, has a scope limited to the `for` loop block. Because `k`'s scope is limited to the `for` loop block, it cannot be seen outside that block. On the other hand, `i` and `j` still can be seen within the `for` loop block. What this means is that scoping has a top-down hierarchical effect--variables defined in outer scopes can still be seen and used within nested scopes; however, variables defined in nested scopes are limited to those scopes. Incidentally, don't worry if you aren't familiar with `for` loops--you learn all about them in the next chapter. For more reasons than visibility, it is important to pay attention to the scope of variables when you declare them. Along with determining the visibility of variables, the scope also determines the lifetime of variables. This means that variables are actually destroyed when program execution leaves their scope. Look at the `GoodbyeWorld` example again: Storage for the integers `i` and `j` is allocated when program execution enters the `main()` method. When the `for` loop block is entered, storage for the integer `k` is allocated. When program execution leaves the `for` loop block, the memory for `k` is freed and the variable is destroyed. Similarly, when program execution leaves `main()`, all the variables in its scope (`i` and `j`) are freed and destroyed. The concepts of variable lifetime and scope become even more important when you start dealing with classes. You'll get a good dose of this in Chapter 5, "Classes, Packages, and Interfaces." ## Arrays An array is a construct that provides for the storage of a list of items of the same type. Array items can have either a simple or composite data type. Arrays also can be multidimensional. Java arrays are declared with square brackets: `[]`. Following are a few examples of array declarations in Java:
    int numbers[];
    char[] letters;

    long grid[][];
If you are familiar with arrays in another language, you may be puzzled by the absence of a number between the square brackets specifying the number of items in the array. Java doesn't allow you to specify the size of an empty array when declaring the array. You must always explicitly set the size of the array with the `new` operator or by assigning a list of items to the array at the time of creation. The `new` operator is covered in the next chapter, "Expressions, Operators, and Control Structures." NOTE: It may seem like a hassle to have to explicitly set the size of an array with the `new` operator. The reason for doing this is because Java doesn't have pointers like C or C++ and therefore doesn't allow you to point anywhere in an array to create new items. Because the Java language handles memory management this way, the bounds-checking problems common with C and C++ have been avoided. Another strange thing you may notice about Java arrays is the optional placement of the square brackets in the array declaration. You can place the square brackets either after the variable type or after the identifier. Following are a couple examples of arrays that have been declared and set to a specific size by using the `new` operator and by assigning a list of items in the array declaration:
    char alphabet[] = new char[26];

    int primes = {7, 11, 13};
More complex structures for storing lists of items, such as stacks and hash tables, are also supported by Java. Unlike arrays, these structures are implemented in Java as classes. You'll get a crash course in some of these other storage mechanisms in Chapter 11, "The Utilities Package." ## Strings In Java, strings are handled by a special class called `String`. Even literal strings are managed internally by an instantiation of a `String` class. An instantiation of a class is simply an object that has been created based on the class description. This method of handling strings is very different from languages like C and C++, where strings are represented simply as an array of characters. Following are a few strings declared using the Java `String` class:
    String message;
    String name = "Mr. Blonde";
At this point, it's not that important to know the `String` class inside and out. You'll learn all the gory details of the `String` class in Chapter 10, "The Language Package." ## Summary This chapter took a look at the core components of the Java language. Hopefully, you now have more insight about why Java has become popular in such a relatively short time. With vast improvements over the weaknesses of the C and C++ languages--arguably the industry's language standards--Java is making huge waves and may conceivably replace C and C++ at some point in the near future. The language elements covered in this chapter are just the tip of the iceberg when it comes to the benefits of programming in Java. Now that you are armed with the fundamentals of the Java language, you are no doubt ready to press onward and learn more about the Java language. The next chapter, "Expressions, Operators, and Control Structures," covers exactly what its title suggests. In it, you learn how to work with and manipulate much of the information you learned about in this chapter. In doing so, you will be able to start writing programs that do a little more than display cute messages on the screen.
| ©Copyright, Macmillan Computer Publishing. All rights reserved.