How Java differs from C and C++

how java is secure and how java compiler works and how java is robust and how java is different from other languages
JohenCorner Profile Pic
JohenCorner,France,Professional
Published Date:02-08-2017
Your Website URL(Optional)
Comment
The Java Language This chapter begins our introduction to the Java language syntax. Because readers come to this book with different levels of programming experience, it is difficult to set the right level for all audiences. We have tried to strike a balance between giving a thorough tour of the language syntax for beginners and providing enough background informa‐ tion so that a more experienced reader can quickly gauge the differences between Java and other languages. Since Java’s syntax is derived from C, we make some comparisons to features of that language, but no prior knowledge of C is necessary. We spend more time on aspects of Java that are different from other languages and less on elemental programming concepts. For example, we’ll take a close look at arrays in Java because they are significantly different from those in other languages. We won’t, on the other hand, spend a lot of time explaining basic language constructs such as loops and control structures. Chapters 5 through 7 will build on this chapter by talking about Java’s object- oriented side and complete the discussion of the core language. Chapter 8 discusses generics, a feature that enhances the way types work in the Java language, allowing you to write certain kinds of classes more flexibly and safely. After that, we dive into the Java APIs and see what we can do with the language. The rest of this book is filled with concise examples that do useful things and if you are left with any questions after these intro‐ ductory chapters, we hope they’ll be answered as you look at the code. Text Encoding Java is a language for the Internet. Since the citizens of the Net speak and write in many different human languages, Java must be able to handle a large number of languages as well. One of the ways in which Java supports internationalization is through the Unicode character set. Unicode is a worldwide standard that supports the scripts of most 83 a 1 languages. The latest version of Java bases its character and string data on the Unicode 6.0 standard, which uses at least two bytes to represent each symbol internally. Java source code can be written using Unicode and stored in any number of character encodings, ranging from a full binary form to ASCII-encoded Unicode character values. This makes Java a friendly language for non-English-speaking programmers who can use their native language for class, method, and variable names just as they can for the text displayed by the application. The Java char type and String class natively support Unicode values. Internally, the text is stored as multibyte characters using the UTF-16 encoding; however, the Java language and APIs make this transparent to you and you will not generally have to think about it. Unicode is also very ASCII-friendly (ASCII is the most common character encoding for English). The first 256 characters are defined to be identical to the first 256 characters in the ISO 8859-1 (Latin-1) character set, so Unicode is effectively backward-compatible with the most common English character sets. Furthermore, one of the most common file encodings for Unicode, called UTF-8, preserves ASCII values in their single byte form. This encoding is used by default in compiled Java class files, so storage remains compact for English text. Most platforms can’t display all currently defined Unicode characters. As a result, Java programs can be written with special Unicode escape sequences. A Unicode character can be represented with this escape sequence: \uxxxx xxxx is a sequence of one to four hexadecimal digits. The escape sequence indicates an ASCII-encoded Unicode character. This is also the form Java uses to output (print) Unicode characters in an environment that doesn’t otherwise support them. Java also comes with classes to read and write Unicode character streams in specific encodings, including UTF-8. Comments Java supports both C-style block comments delimited by / and / and C++-style line comments indicated by//: / This is a multiline comment. / 1. For more information about Unicode, see http://www.unicode.org. Ironically, one of the scripts listed as “obsolete and archaic” and not currently supported by the Unicode standard is Javanese—a historical language of the people of the Island of Java. 84 Chapter 4: The Java Language a // This is a single-line comment // and so // is this Block comments have both a beginning and end sequence and can cover large ranges of text. However, they cannot be “nested,” meaning that you can’t have a block comment inside of a block comment without the compiler getting confused. Single-line comments have only a start sequence and are delimited by the end of a line; extra // indicators inside a single line have no effect. Line comments are useful for short comments within methods; they don’t conflict with block comments, so you can still comment out larger chunks of code in which they are nested. Javadoc Comments A block comment beginning with/ indicates a special doccomment. A doc comment is designed to be extracted by automated documentation generators, such as the JDK’s javadoc program. A doc comment is terminated by the next /, just as with a regular block comment. Within the doc comment, lines beginning with are interpreted as special instructions for the documentation generator, giving it information about the source code. By convention, each line of a doc comment begins with a , as shown in the following example, but this is optional. Any leading spacing and the on each line are ignored: / I think this class is possibly the most amazing thing you will ever see. Let me tell you about my own personal vision and motivation in creating it. p It all began when I was a small child, growing up on the streets of Idaho. Potatoes were the rage, and life was good... see PotatoPeeler see PotatoMasher author John 'Spuds' Smith version 1.00, 19 Dec 2006 / class Potato javadoc creates HTML documentation for classes by reading the source code and pulling out the embedded comments and tags. In this example, the tags cause author and version information to be presented in the class documentation. Thesee tags produce hypertext links to the related class documentation. The compiler also looks at the doc comments; in particular, it is interested in thedep recated tag, which means that the method has been declared obsolete and should be avoided in new programs. The fact that a method is deprecated is noted in the compiled class file so a warning message can be generated whenever you use a deprecated feature in your code (even if the source isn’t available). Comments 85 a Doc comments can appear above class, method, and variable definitions, but some tags may not be applicable to all of these. For example, theexception tag can only be applied to methods. Table 4-1 summarizes the tags used in doc comments. Table 4-1. Doc comment tags Tag Description Applies to see Associated class name Class, method, or variable author Author name Class version Version string Class param Parameter name and description Method Description of return value Method return exception Exception name and description Method deprecated Declares an item to be obsolete Class, method, or variable since Notes API version when item was added Variable Javadoc as metadata Javadoc tags in doc comments represent metadata about the source code; that is, they add descriptive information about the structure or contents of the code that is not, strictly speaking, part of the application. Some additional tools extend the concept of Javadoc-style tags to include other kinds of metadata about Java programs that are car‐ ried with the compiled code and can more readily be used by the application to affect its compilation or runtime behavior. The Java annotations facility provides a more for‐ mal and extensible way to add metadata to Java classes, methods, and variables. We’ll talk about annotations in Chapter 7. However, we should mention that there is a dep recated annotation that has the same meaning as that of the Javadoc tag of the same name, and you may prefer to use that. Types The type system of a programming language describes how its data elements (variables and constants) are associated with storage in memory and how they are related to one another. In a statically typed language, such as C or C++, the type of a data element is a simple, unchanging attribute that often corresponds directly to some underlying hardware phenomenon, such as a register or a pointer value. In a more dynamic lan‐ guage such as Smalltalk or Lisp, variables can be assigned arbitrary elements and can effectively change their type throughout their lifetime. A considerable amount of over‐ head goes into validating what happens in these languages at runtime. Scripting lan‐ guages such as Perl achieve ease of use by providing drastically simplified type systems in which only certain data elements can be stored in variables, and values are unified into a common representation, such as strings. 86 Chapter 4: The Java Language aJava combines many of the best features of both statically and dynamically typed lan‐ guages. As in a statically typed language, every variable and programming element in Java has a type that is known at compile time, so the runtime system doesn’t normally have to check the validity of assignments between types while the code is executing. Unlike traditional C or C++, Java also maintains runtime information about objects and uses this to allow truly dynamic behavior. Java code may load new types at runtime and use them in fully object-oriented ways, allowing casting and full polymorphism (ex‐ tending of types). Java code may also “reflect” upon or examine its own types at runtime, allowing advanced kinds of application behavior such as interpreters that can interact with compiled programs dynamically. Java data types fall into two categories. Primitive types represent simple values that have built-in functionality in the language; they are fixed elements, such as literal constants and numbers. Reference types (or class types) include objects and arrays; they are called reference types because they “refer to” a large data type that is passed “by reference,” as we’ll explain shortly. Generic types are really just a kind of composition (combination) of class types and are therefore reference types as well. Primitive Types Numbers, characters, and Boolean values are fundamental elements in Java. Unlike some other (perhaps more pure) object-oriented languages, they are not objects. For those situations where it’s desirable to treat a primitive value as an object, Java provides “wrapper” classes. The major advantage of treating primitive values as special is that the Java compiler and runtime can more readily optimize their implementation. Primitive values and computations can still be mapped down to hardware as they always have been in lower-level languages. Later we’ll see how Java can automatically convert be‐ tween primitive values and their object wrappers as needed to partially mask the dif‐ ference between the two. We’ll explain what that means in more detail in the next chapter when we discuss boxing and unboxing of primitive values. An important portability feature of Java is that primitive types are precisely defined. For example, you never have to worry about the size of anint on a particular platform; it’s always a 32-bit, signed, two’s complement number. Table 4-2 summarizes Java’s primitive types. Table 4-2. Java primitive data types Type Definition boolean true orfalse 16-bit, Unicode character char byte 8-bit, signed, two’s complement integer short 16-bit, signed, two’s complement integer int 32-bit, signed, two’s complement integer Types 87 aType Definition long 64-bit, signed, two’s complement integer float 32-bit, IEEE 754, floating-point value 64-bit, IEEE 754 double Those of you with a C background may notice that the primitive types look like an idealization of C scalar types on a 32-bit machine, and you’re absolutely right. That’s how they’re supposed to look. The 16- bit characters were forced by Unicode, and ad hoc pointers were de‐ leted for other reasons. But overall, the syntax and semantics of Java primitive types derive from C. Floating-point precision Floating-point operations in Java follow the IEEE 754 international specification, which means that the result of floating-point calculations is normally the same on different Java platforms. However, Java allows for extended precision on platforms that support it. This can introduce extremely small-valued and arcane differences in the results of high-precision operations. Most applications would never notice this, but if you want to ensure that your application produces exactly the same results on different platforms, you can use the special keyword strictfp as a class modifier on the class containing the floating-point manipulation (we cover classes in the next chapter). The compiler then prohibits these platform-specific optimizations. Variable declaration and initialization Variables are declared inside of methods and classes with a type name followed by one or more comma-separated variable names. For example: int foo; double d1, d2; boolean isFun; Variables can optionally be initialized with an expression of the appropriate type when they are declared: int foo = 42; double d1 = 3.14, d2 = 2 3.14; boolean isFun = true; Variables that are declared as members of a class are set to default values if they aren’t initialized (see Chapter 5). In this case, numeric types default to the appropriate flavor of zero, characters are set to the null character (\0), and Boolean variables have the value false. Local variables, which are declared inside a method and live only for the duration of a method call, on the other hand, must be explicitly initialized before they 88 Chapter 4: The Java Language a can be used. As we’ll see, the compiler enforces this rule so there is no danger of forgetting. Integer literals Integer literals can be specified in octal (base 8), decimal (base 10), or hexadecimal (base 16). A decimal integer is specified by a sequence of digits beginning with one of the characters 1–9: int i = 1230; Octal numbers are distinguished from decimal numbers by a leading zero: int i = 01230; // i = 664 decimal A hexadecimal number is denoted by the leading characters0x or0X (zero “x”), followed by a combination of digits and the characters a–f or A–F, which represent the decimal values 10–15: int i = 0xFFFF; // i = 65535 decimal Integer literals are of typeint unless they are suffixed with anL, denoting that they are to be produced as along value: long l = 13L; long l = 13; // equivalent: 13 is converted from type int (The lowercase letter l is also acceptable but should be avoided because it often looks like the number1.) When a numeric type is used in an assignment or an expression involving a “larger” type with a greater range, it can be promoted to the bigger type. In the second line of the previous example, the number 13 has the default type of int, but it’s promoted to typelong for assignment to the long variable. Certain other numeric and comparison operations also cause this kind of arithmetic promotion, as do mathematical expressions involving more than one type. For example, when multiplying a byte value by an int value, the compiler promotes thebyte to anint first: byte b = 42; int i = 43; int result = b i; // b is promoted to int before multiplication A numeric value can never go the other way and be assigned to a type with a smaller range without an explicit cast, however: int i = 13; byte b = i; // Compile-time error, explicit cast needed byte b = (byte) i; // OK Conversions from floating-point to integer types always require an explicit cast because of the potential loss of precision. Types 89 a Finally, we should note that if you are using Java 7 or later, you can add a bit of formatting to your numeric literals by utilizing the “_” underscore character between digits. So if you have particularly large strings of digits, you can break them up as in the following examples: int RICHARD_NIXONS_SSN = 567_68_0515; int for_no_reason = 1___2___3; int JAVA_ID = 0xCAFE_BABE; Underscores may only appear between digits, not at the beginning or end of a number or next to the “L” long integer signifier. Floating-point literals Floating-point values can be specified in decimal or scientific notation. Floating-point literals are of typedouble unless they are suffixed with anf orF denoting that they are to be produced as afloat value. And just as with integer literals, in Java 7 you may use “_” underscore characters to format floating-point numbers—but only between digits, not at the beginning, end, or next to the decimal point or “F” signifier of the number. double d = 8.31; double e = 3.00e+8; float f = 8.31F; float g = 3.00e+8F; float pi = 3.14_159_265_358; Binary literals A new feature of Java 7 is the introduction of binary literal values. This allows you to write out binary values directly by prefixing the number with a “0b” or “0B” (zero B). byte one = (byte)0b00000001; byte two = (byte)0b00000010; byte four = (byte)0b00000100; byte sixteen = (byte)0b00001000; int cafebabe = 0b11001010111111101011101010111110; long lots_o_ones = (long)0b11111111111111111111111111111111111111111111111L; Character literals A literal character value can be specified either as a single-quoted character or as an escaped ASCII or Unicode sequence: char a = 'a'; char newline = '\n'; char smiley = '\u263a'; 90 Chapter 4: The Java Language aReference Types In an object-oriented language like Java, you create new, complex data types from simple primitives by creating aclass. Each class then serves as a new type in the language. For example, if we create a new class calledFoo in Java, we are also implicitly creating a new type calledFoo. The type of an item governs how it’s used and where it can be assigned. As with primitives, an item of typeFoo can, in general, be assigned to a variable of type Foo or passed as an argument to a method that accepts aFoo value. A type is not just a simple attribute. Classes can have relationships with other classes and so do the types that they represent. All classes in Java exist in a parent-child hier‐ archy, where a child class or subclass is a specialized kind of its parent class. The corre‐ sponding types have the same relationship, where the type of the child class is considered a subtype of the parent class. Because child classes inherit all of the functionality of their parent classes, an object of the child’s type is in some sense equivalent to or an extension of the parent type. An object of the child type can be used in place of an object of the parent’s type. For example, if you create a new class, Cat, that extendsAnimal, the new type, Cat, is considered a subtype of Animal. Objects of type Cat can then be used anywhere an object of type Animal can be used; an object of type Cat is said to be assignable to a variable of typeAnimal. This is called subtype polymorphism and is one of the primary features of an object-oriented language. We’ll look more closely at classes and objects in Chapter 5. Primitive types in Java are used and passed “by value.” In other words, when a primitive value like an int is assigned to a variable or passed as an argument to a method, it’s simply copied. Reference types (class types), on the other hand, are always accessed “by reference.” A reference is simply a handle or a name for an object. What a variable of a reference type holds is a “pointer” to an object of its type (or of a subtype, as described earlier). When the reference is assigned to a variable or passed to a method, only the reference is copied, not the object to which it’s pointing. A reference is like a pointer in C or C++, except that its type is so strictly enforced. The reference value itself can’t be explicitly created or changed. A variable acquires a reference value only through as‐ signment to an appropriate object. Let’s run through an example. We declare a variable of typeFoo, calledmyFoo, and assign 2 it an appropriate object: Foo myFoo = new Foo(); Foo anotherFoo = myFoo; 2. The comparable code in C++ would be: Foo& myFoo = (new Foo()); Foo& anotherFoo = myFoo; Types 91 a myFoo is a reference-type variable that holds a reference to the newly constructed Foo object. (For now, don’t worry about the details of creating an object; we’ll cover that in Chapter 5.) We declare a secondFoo type variable,anotherFoo, and assign it to the same object. There are now two identical references : myFoo and anotherFoo, but only one actual Foo object instance. If we change things in the state of the Foo object itself, we see the same effect by looking at it with either reference. Object references are passed to methods in the same way. In this case, either myFoo or anotherFoo would serve as equivalent arguments: myMethod( myFoo ); An important, but sometimes confusing, distinction to make at this point is that the reference itself is a value and that value is copied when it is assigned to a variable or passed in a method call. Given our previous example, the argument passed to a method (a local variable from the method’s point of view) is actually a third reference to the Foo object, in addition tomyFoo andanotherFoo. The method can alter the state of theFoo object through that reference (calling its methods or altering its variables), but it can’t change the caller’s notion of the reference tomyFoo: that is, the method can’t change the caller’s myFoo to point to a different Foo object; it can change only its own reference. This will be more obvious when we talk about methods later. Java differs from C++ in this respect. If you need to change a caller’s reference to an object in Java, you need an additional level of indirection. The caller would have to wrap the reference in another object so that both could share the reference to it. Reference types always point to objects, and objects are always defined by classes. How‐ ever, two special kinds of reference types—arrays and interfaces—specify the type of object they point to in a slightly different way. Arrays in Java have a special place in the type system. They are a special kind of object automatically created to hold a collection of some other type of object, known as the base type. Declaring an array type reference implicitly creates the new class type designed as a container for its base type, as you’ll see in the next chapter. Interfaces are a bit sneakier. An interface defines a set of methods and gives it a corre‐ sponding type. An object that implements the methods of the interface can be referred to by that interface type, as well as its own type. Variables and method arguments can be declared to be of interface types, just like other class types, and any object that im‐ plements the interface can be assigned to them. This adds flexibility in the type system and allows Java to cross the lines of the class hierarchy and make objects that effectively have many types. We’ll cover interfaces in the next chapter as well. Generic types or parameterized types, as we mentioned earlier, are an extension of the Java class syntax that allows for additional abstraction in the way classes work with other Java types. Generics allow for specialization of classes by the user without changing any of the original class’s code. We cover generics in detail in Chapter 8. 92 Chapter 4: The Java Language aA Word About Strings Strings in Java are objects; they are therefore a reference type.String objects do, how‐ ever, have some special help from the Java compiler that makes them look more like primitive types. Literal string values in Java source code are turned intoString objects by the compiler. They can be used directly, passed as arguments to methods, or assigned toString type variables: System.out.println( "Hello, World..." ); String s = "I am the walrus..."; String t = "John said: \"I am the walrus...\""; The+ symbol in Java is “overloaded” to perform string concatenation as well as regular numeric addition. Along with its sister+=, this is the only overloaded operator in Java: String quote = "Four score and " + "seven years ago,"; String more = quote + " our" + " fathers" + " brought..."; Java builds a singleString object from the concatenated strings and provides it as the result of the expression. We discuss theString class and all things text-related in great detail in Chapter 10. Statements and Expressions Java statements appear inside methods and classes; they describe all activities of a Java program. Variable declarations and assignments, such as those in the previous section, are statements, as are basic language structures such as if/then conditionals and loops. int size = 5; if ( size 10 ) doSomething(); for( int x = 0; x size; x++ ) ... Expressions produce values; an expression is evaluated to produce a result that is to be used as part of another expression or in a statement. Method calls, object allocations, and, of course, mathematical expressions are examples of expressions. Technically, be‐ cause variable assignments can be used as values for further assignments or operations (in somewhat questionable programming style), they can be considered to be both statements and expressions. new Object(); Math.sin( 3.1415 ); 42 64; One of the tenets of Java is to keep things simple and consistent. To that end, when there are no other constraints, evaluations and initializations in Java always occur in the order in which they appear in the code—from left to right, top to bottom. We’ll see this rule used in the evaluation of assignment expressions, method calls, and array indexes, to name a few cases. In some other languages, the order of evaluation is more complicated Statements and Expressions 93 a or even implementation-dependent. Java removes this element of danger by precisely and simply defining how the code is evaluated. This doesn’t mean you should start writing obscure and convoluted statements, however. Relying on the order of evaluation of expressions in complex ways is a bad programming habit, even when it works. It produces code that is hard to read and harder to modify. Statements Statements and expressions in Java appear within a code block. A code block is syntac‐ tically a series of statements surrounded by an open curly brace () and a close curly brace (). The statements in a code block can include variable declarations and most of the other sorts of statements and expressions we mentioned earlier: int size = 5; setName("Max"); ... Methods, which look like C functions, are in a sense just code blocks that take parameters and can be called by their names—for example, the methodsetUpDog(): setUpDog( String name ) int size = 5; setName( name ); ... Variable declarations are limited in scope to their enclosing code block—that is, they can’t be seen outside of the nearest set of braces: int i = 5; i = 6; // Compile-time error, no such variable i In this way, code blocks can be used to arbitrarily group other statements and variables. The most common use of code blocks, however, is to define a group of statements for use in a conditional or iterative statement. if/else conditionals We can define anif/else clause as follows: if ( condition ) statement; else statement; 94 Chapter 4: The Java Language a (The whole of the preceding example is itself a statement and could be nested within another if/else clause.) The if clause has the common functionality of taking two different forms: a “one-liner” or a block. The block form is as follows: if ( condition ) statement; statement; ... else statement; statement; ... Thecondition is a Boolean expression. A Boolean expression is atrue orfalse value or an expression that evaluates to one of those. For example i == 0 is a Boolean ex‐ pression that tests whether the integeri holds the value0. In the second form, the statements are in code blocks, and all their enclosed statements are executed if the corresponding (if or else) branch is taken. Any variables declared within each block are visible only to the statements within the block. Like the if/ else conditional, most of the remaining Java statements are concerned with controlling the flow of execution. They act for the most part like their namesakes in other languages. do/while loops Thedo andwhile iterative statements have the familiar functionality; their conditional test is also a Boolean expression: while ( condition ) statement; do statement; while ( condition ); For example: while( queue.isEmpty() ) wait(); Unlike while or for loops (which we’ll see next) that test their conditions first, a do- while loop always executes its statement body at least once. The for loop The most general form of thefor loop is also a holdover from the C language: for ( initialization; condition; incrementor ) statement; The variable initialization section can declare or initialize variables that are limited to the scope of thefor statement. Thefor loop then begins a possible series of rounds in Statements and Expressions 95 awhich the condition is first checked and, if true, the body statement (or block) is exe‐ cuted. Following each execution of the body, the incrementor expressions are evaluated to give them a chance to update variables before the next round begins: for ( int i = 0; i 100; i++ ) System.out.println( i ); int j = i; ... This loop will execute 100 times, printing values from 0 to 99. Note that the variablej is local to the block (visible only to statements within it) and will not be accessible to the code “after” the for loop. If the condition of a for loop returns false on the first check, the body and incrementor section will never be executed. You can use multiple comma-separated expressions in the initialization and incremen‐ tation sections of thefor loop. For example: for (int i = 0, j = 10; i j; i++, j ) ... You can also initialize existing variables from outside the scope of thefor loop within the initializer block. You might do this if you wanted to use the end value of the loop variable elsewhere: int x; for( x = 0; hasMoreValue(); x++ ) getNextValue(); System.out.println( x ); The enhanced for loop Java’s auspiciously dubbed “enhancedfor loop” acts like the “foreach” statement in some other languages, iterating over a series of values in an array or other type of collection: for ( varDeclaration : iterable ) statement; The enhanced for loop can be used to loop over arrays of any type as well as any kind of Java object that implements the java.lang.Iterable interface. This includes most of the classes of the Java Collections API. We’ll talk about arrays in this and the next chapter; Chapter 11 covers Java Collections. Here are a couple of examples: int arrayOfInts = new int 1, 2, 3, 4 ; for( int i : arrayOfInts ) System.out.println( i ); ListString list = new ArrayListString(); list.add("foo"); list.add("bar"); 96 Chapter 4: The Java Language a for( String s : list ) System.out.println( s ); Again, we haven’t discussed arrays or theList class and special syntax in this example. What we’re showing here is the enhanced for loop iterating over an array of integers and also a list of string values. In the second case, the List implements the Iterable interface and thus can be a target of thefor loop. switch statements The most common form of the Java switch statement takes an integer (or a numeric type argument that can be automatically “promoted” to an integer type), a string type argument, or an “enum” type (discussed shortly) and selects among a number of alter‐ 3 native, constantcase branches: switch ( expression ) case constantExpression : statement; case constantExpression :statement; ... default : statement; The case expression for each branch must evaluate to a different constant integer or string value at compile time. Strings are compared using theString equals() method, which we’ll discuss in more detail in Chapter 10. An optional default case can be specified to catch unmatched conditions. When executed, the switch simply finds the branch matching its conditional expression (or the default branch) and executes the corresponding statement. But that’s not the end of the story. Perhaps counterintuitively, theswitch statement then continues executing branches after the matched branch until it hits the end of the switch or a special statement called break. Here are a couple of examples: int value = 2; switch( value ) case 1: System.out.println( 1 ); case 2: System.out.println( 2 ); case 3: System.out.println( 3 ); 3. Strings inswitch statements were added in Java 7. Statements and Expressions 97 a // prints 2, 3 Usingbreak to terminate each branch is more common: int retValue = checkStatus(); switch ( retVal ) case MyClass.GOOD : // something good break; case MyClass.BAD : // something bad break; default : // neither one break; In this example, only one branch—GOOD, BAD, or the default—is executed. The “fall through” behavior of the switch is justified when you want to cover several possible case values with the same statement without resorting to a bunch ofif/else statements: int value = getSize(); switch( value ) case MINISCULE: case TEENYWEENIE: case SMALL: System.out.println("Small" ); break; case MEDIUM: System.out.println("Medium" ); break; case LARGE: case EXTRALARGE: System.out.println("Large" ); break; This example effectively groups the six possible values into three cases. Enumerations and switch statements Enumerations are intended to replace much of the usage of integer constants for situa‐ tions like the one just discussed with a typesafe alternative. Enumerations use objects as their values instead of integers but preserve the notion of ordering and comparability. We’ll see in Chapter 5 that enumerations are declared much like classes and that the values can be “imported” into the code of your application to be used just like constants. For example: 98 Chapter 4: The Java Language a enum Size Small, Medium, Large You can use enumerations in switches in the same way that the previous switch examples used integer constants. In fact, it is much safer to do so because the enumerations have real types and the compiler does not let you mistakenly add cases that do not match any value or mix values from different enumerations. // usage Size size = ...; switch ( size ) case Small: ... case Medium: ... case Large: ... Chapter 5 provides more details about enumerations. break/continue The Java break statement and its friend continue can also be used to cut short a loop or conditional statement by jumping out of it. A break causes Java to stop the current block statement and resume execution after it. In the following example, thewhile loop goes on endlessly until thecondition() method returns true, triggering abreak state‐ ment that stops the loop and proceeds at the point marked “after while.” while( true ) if ( condition() ) break; // after while Acontinue statement causesfor andwhile loops to move on to their next iteration by returning to the point where they check their condition. The following example prints the numbers 0 through 99, skipping number 33. for( int i=0; i 100; i++ ) if ( i == 33 ) continue; System.out.println( i ); Thebreak andcontinue statements look like those in the C language, but Java’s forms have the additional ability to take a label as an argument and jump out multiple levels to the scope of the labeled point in the code. This usage is not very common in day-to- day Java coding, but may be important in special cases. Here is an outline: labelOne: while ( condition ) ... Statements and Expressions 99 a labelTwo: while ( condition ) ... // break or continue point // after labelTwo // after labelOne Enclosing statements, such as code blocks, conditionals, and loops, can be labeled with identifiers like labelOne andlabelTwo. In this example, abreak or continue without argument at the indicated position has the same effect as the earlier examples. Abreak causes processing to resume at the point labeled “after labelTwo”; acontinue immedi‐ ately causes thelabelTwo loop to return to its condition test. The statementbreak labelTwo at the indicated point has the same effect as an ordinary break, but break labelOne breaks both levels and resumes at the point labeled “after labelOne.” Similarly, continue labelTwo serves as a normal continue, but continue labelOne returns to the test of the labelOne loop. Multilevel break and continue statements remove the main justification for the evilgoto statement in C/C++. There are a few Java statements we aren’t going to discuss right now. The try , catch, and finally statements are used in exception handling, as we’ll discuss later in this chapter. The synchronized statement in Java is used to coordinate access to statements among multiple threads of execution; see Chapter 9 for a discussion of thread synchronization. Unreachable statements On a final note, we should mention that the Java compiler flags “unreachable” statements as compile-time errors. An unreachable statement is one that the compiler determines won’t be called at all. Of course, many methods may never actually be called in your code, but the compiler detects only those that it can “prove” are never called by simple checking at compile time. For example, a method with an unconditional return state‐ ment in the middle of it causes a compile-time error, as does a method with a conditional that the compiler can tell will never be fulfilled: if (1 2) return; // unreachable statements Expressions An expression produces a result, or value, when it is evaluated. The value of an expres‐ sion can be a numeric type, as in an arithmetic expression; a reference type, as in an object allocation; or the special type,void, which is the declared type of a method that doesn’t return a value. In the last case, the expression is evaluated only for its side 100 Chapter 4: The Java Language a effects; that is, the work it does aside from producing a value. The type of an expression is known at compile time. The value produced at runtime is either of this type or in the case of a reference type, a compatible (assignable) subtype. Operators Java supports almost all standard operators from the C language. These operators also have the same precedence in Java as they do in C, as shown in Table 4-3. Table 4-3. Java operators Precedence Operator Operand type Description 1 ++, — Arithmetic Increment and decrement 1 +, - Arithmetic Unary plus and minus 1 Integral Bitwise complement 1 Boolean Logical complement 1 ( type ) Any Cast 2 , /, % Arithmetic Multiplication, division, remainder 3 +, - Arithmetic Addition and subtraction 3 + String String concatenation 4 Integral Left shift 4 Integral Right shift with sign extension 4 Integral Right shift with no extension 5 , =, , = Arithmetic Numeric comparison 5 Object Type comparison instanceof 6 ==, = Primitive Equality and inequality of value 6 ==, = Object Equality and inequality of reference 7 & Integral Bitwise AND 7 & Boolean Boolean AND 8 Integral Bitwise XOR 8 Boolean Boolean XOR 9 Integral Bitwise OR 9 Boolean Boolean OR 10 && Boolean Conditional AND 11 Boolean Conditional OR 12 ?: N/A Conditional ternary operator 13 = Any Assignment We should also note that the percent (%) operator is not strictly a modulo, but a re‐ mainder, and can have a negative value. Statements and Expressions 101 a Java also adds some new operators. As we’ve seen, the+ operator can be used withString values to perform string concatenation. Because all integral types in Java are signed values, the operator can be used to perform a right-arithmetic-shift operation with sign extension. The operator treats the operand as an unsigned number and per‐ forms a right-arithmetic-shift with no sign extension. Thenew operator is used to create objects; we will discuss it in detail shortly. Assignment While variable initialization (i.e., declaration and assignment together) is considered a statement with no resulting value, variable assignment alone is an expression: int i, j; // statement i = 5; // both expression and statement Normally, we rely on assignment for its side effects alone, but an assignment can be used as a value in another part of an expression: j = ( i = 5 ); Again, relying on order of evaluation extensively (in this case, using compound assign‐ ments in complex expressions) can make code obscure and hard to read. The null value The expression null can be assigned to any reference type. It means “no reference.” A null reference can’t be used to reference anything and attempting to do so generates a NullPointerException at runtime. Variable access The dot (.) operator is used to select members of a class or object instance. (We’ll talk about those in detail in the following chapters.) It can retrieve the value of an instance variable (of an object) or a static variable (of a class). It can also specify a method to be invoked on an object or class: int i = myObject.length; String s = myObject.name; myObject.someMethod(); A reference-type expression can be used in compound evaluations by selecting further variables or methods on the result: int len = myObject.name.length(); int initialLen = myObject.name.substring(5, 10).length(); Here we have found the length of ourname variable by invoking thelength() method of the String object. In the second case, we took an intermediate step and asked for a substring of the name string. The substring method of the String class also returns a String reference, for which we ask the length. Compounding operations like this is also 102 Chapter 4: The Java Language a