Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Monday, 13 June 2016

Objects in Java: Accessing Fields and Methods

Inside a class, we can access variables and call methods of the class directly by name. Here’s an example that expands on our Pendulum:
 class Pendulum {  
 ...  
 void resetEverything() {mass = 1.0;  
 length = 1.0;  
 cycles = 0;  
 ...  
 float startingPosition = getPosition( 0.0 );  
 }  
 ...  
 }  
Other classes access members of an object through a reference, using the dot selector notation that we discussed in the last chapter:
 class TextBook {  
 ...  
 void showPendulum() {  
 Pendulum bob = new Pendulum();  
 ...  
 int i = bob.cycles;  
 bob.resetEverything();  
 bob.mass = 1.01;  
 ...  
 }  
 ...  
 }  
Here we have created a second class, TextBook, that uses a Pendulum object. It creates an instance in showPendulum() and then invokes methods and accesses variables of the object through the reference bob. Several factors affect whether class members can be accessed from another class. You can use the visibility modifiers public, private, and protected to control access; classes can also be placed into a package, which affects their scope. The private modifier, for example, designates a variable or method for use only by other members of the class itself. In the previous example, we could change the declaration of our variable cy cles to private:
 class Pendulum {  
 ...  
 private int cycles;  
 ...  
Now we can’t access cycles from TextBook:
 class TextBook {  
 ...  
 void showPendulum() {  
 ...  
 int i = bob.cycles; // Compile-time error  
If we still need to access cycles in some capacity, we might add a public getCycles() method to the Pendulum class. (Creating accessor methods like this is a good design rule because it allows future flexibility in changing the type or behavior of the value.) We’ll take a detailed look at packages, access modifiers, and how they affect the visibility of variables and methods.

Classes in Java

Classes are the building blocks of a Java application. A class can contain methods (functions), variables, initialization code, and, as we’ll discuss later, other classes. It serves as a blueprint for making class instances, which are runtime objects (individual copies) that implement the class structure. You declare a class with the class keyword. Methods and variables of the class appear inside the braces of the class declaration:
 class Pendulum {  
 float mass;  
 float length = 1.0f;  
 int cycles;  
 float getPosition ( float time ) {  
 ...  
 }  
 ...  
 }  
The Pendulum class contains three variables: mass, length, and cycles. It also defines a method called getPosition(), which takes a float value as an argument and returns a float value as a result. Variables and method declarations can appear in any order, but variable initializers can’t make “forward references” to other variables that appear later. Once we’ve defined the Pendulum class, we can create a Pendulum object (an instance of that class) as follows:
 Pendulum p;  
 p = new Pendulum();  
Recall that our declaration of the variable p doesn’t create a Pendulum object; it simply creates a variable that refers to an object of type Pendulum. We still had to create the object, using the new keyword, as shown in the second line of the preceding code snippet. Now that we’ve created a Pendulum object, we can access its variables and methods, as we’ve already seen many times:
 p.mass = 5.0;  
 float pos = p.getPosition( 1.0 );  
Two kinds of variables can be defined in a class: instance variables and static variables. Every object instance has its own set of instance variables; the values of these variables in one instance of an object can differ from the values in another object. We’ll talk about static variables later, which, in contrast, are shared among all instances of an object. In either case, if you don’t initialize a variable when you declare it, it’s given a default value appropriate for its type (null, zero, or false). The figure below shows a hypothetical TextBook application that uses two instances of Pendu lum through the reference-type variables bigPendulum and smallPendulum. Each of these Pendulum objects has its own copy of mass, length, and cycles. As with variables, methods defined in a class may be instance methods or static methods. An instance method is associated with just one instance of the class, but the relationship isn’t quite as simple as it is for variables. Instance methods are accessed through an object instance, but the object doesn’t really have its own “copy” of the methods (there is no duplication of code). Instead, the association means that instance methods can “see” and operate on the values of the instance variables of the object. As you’ll see when we talk about subclassing, there’s more to learn about how methods see variables. In that chapter, we’ll also discuss how instance methods can be “overridden” in child classes—a very important feature of object-oriented design. Both aspects differ from static methods, which we’ll see are really more like global functions, as they are associated with a class by name only.

Objects in Java

The term object-oriented design refers to the art of decomposing an application into some number of objects, which are self-contained application components that work together. The goal is to break your problem down into a number of smaller problems that are simpler and easier to handle and maintain. Object-based designs have proven themselves over the years, and object-oriented languages such as Java provide a strong foundation for writing applications from the very small to the very large. Java was designed from the ground up to be an object-oriented language, and all of the Java APIs and libraries are built around solid object-based design patterns. An object design “methodology” is a system or a set of rules created to help you break down your application into objects. Often this means mapping real-world entities and concepts (sometimes called the “problem domain”) into application components. Various methodologies attempt to help you factor your application into a good set of reusable objects. This is good in principle, but the problem is that good object-oriented design is still more art than science. While you can learn from the various off-the-shelf design methodologies, none of them will help you in all situations. The truth is that there is no substitute for experience.

Saturday, 11 June 2016

The Java Language:Arrays:Inside Arrays

We said earlier that arrays are instances of special array classes in the Java language. If arrays have classes, where do they fit into the class hierarchy and how are they related? These are good questions, but we need to talk more about the object-oriented aspects of Java before answering them. That’s our next subject. For now, take it on faith that arrays fit into the class hierarchy.

The Java Language:Arrays:Multidimensional Arrays

Java supports multidimensional arrays in the form of arrays of array type objects. You create a multidimensional array with C-like syntax, using multiple bracket pairs, one for each dimension. You also use this syntax to access elements at various positions within the array. Here’s an example of a multidimensional array that represents a chess board:
 ChessPiece [][] chessBoard;  
 chessBoard = new ChessPiece [8][8];  
 chessBoard[0][0] = new ChessPiece.Rook;  
 chessBoard[1][0] = new ChessPiece.Pawn;  
 ...  
Here, chessBoard is declared as a variable of type ChessPiece[][] (i.e., an array of ChessPiece arrays). This declaration implicitly creates the type ChessPiece[] as well. The example illustrates the special form of the new operator used to create a multidimensional array. It creates an array of ChessPiece[] objects and then, in turn, makes each element into an array of ChessPiece objects. We then index chessBoard to specify values for particular ChessPiece elements. (We’ll neglect the color of the pieces here.) Of course, you can create arrays with more than two dimensions. Here’s a slightly impractical example:
 Color [][][] rgbCube = new Color [256][256][256];  
 rgbCube[0][0][0] = Color.black;  
 rgbCube[255][255][0] = Color.yellow;  
 ...  
We can specify a partial index of a multidimensional array to get a subarray of array type objects with fewer dimensions. In our example, the variable chessBoard is of type ChessPiece[][]. The expression chessBoard[0] is valid and refers to the first element of chessBoard, which, in Java, is of type ChessPiece[]. For example, we can populate our chess board one row at a time:
 ChessPiece [] homeRow = {  
 new ChessPiece("Rook"), new ChessPiece("Knight"),  
 new ChessPiece("Bishop"), new ChessPiece("King"),  
 new ChessPiece("Queen"), new ChessPiece("Bishop"),  
 new ChessPiece("Knight"), new ChessPiece("Rook")  
 };  
chessBoard[0] = homeRow;
We don’t necessarily have to specify the dimension sizes of a multidimensional array with a single new operation. The syntax of the new operator lets us leave the sizes of some dimensions unspecified. The size of at least the first dimension (the most significant dimension of the array) has to be specified, but the sizes of any number of trailing, less significant array dimensions may be left undefined. We can assign appropriate arraytype values later. We can create a checkerboard of Boolean values (which is not quite sufficient for a real game of checkers either) using this technique:
 boolean [][] checkerBoard;  
 checkerBoard = new boolean [8][];  
Here, checkerBoard is declared and created, but its elements, the eight boolean[] objects of the next level, are left empty. Thus, for example, checkerBoard[0] is null until we explicitly create an array and assign it, as follows:
 checkerBoard[0] = new boolean [8];  
 checkerBoard[1] = new boolean [8];  
 ...  
 checkerBoard[7] = new boolean [8];  
The code of the previous two examples is equivalent to:
 boolean [][] checkerBoard = new boolean [8][8];  
One reason we might want to leave dimensions of an array unspecified is so that we can store arrays given to us by another method. Note that because the length of the array is not part of its type, the arrays in the checkerboard do not necessarily have to be of the same length; that is, multidimensional arrays don’t have to be rectangular. Here’s a defective (but perfectly legal in Java) checkerboard:
 checkerBoard[2] = new boolean [3];  
 checkerBoard[3] = new boolean [10];  
And here’s how you could create and initialize a triangular array:
 int [][] triangle = new int [5][];  
 for (int i = 0; i < triangle.length; i++) {  
 triangle[i] = new int [i + 1];  
 for (int j = 0; j < i + 1; j++)  
 triangle[i][j] = i + j;  
 }  

The Java Language:Arrays:Anonymous Arrays

Often it is convenient to create “throwaway” arrays, arrays that are used in one place and never referenced anywhere else. Such arrays don’t need a name because you never need to refer to them again in that context. For example, you may want to create a collection of objects to pass as an argument to some method. It’s easy enough to create a normal, named array, but if you don’t actually work with the array (if you use the array only as a holder for some collection), you shouldn’t need to do this. Java makes it easy to create “anonymous” (i.e., unnamed) arrays. Let’s say you need to call a method named setPets(), which takes an array of Animal objects as arguments. Provided Cat and Dog are subclasses of Animal, here’s how to call setPets() using an anonymous array:
 Dog pokey = new Dog ("gray");  
 Cat boojum = new Cat ("grey");  
 Cat simon = new Cat ("orange");  
 setPets ( new Animal [] { pokey, boojum, simon });  
The syntax looks similar to the initialization of an array in a variable declaration. We implicitly define the size of the array and fill in its elements using the curly-brace notation. However, because this is not a variable declaration, we have to explicitly use the new operator and the array type to create the array object. Anonymous arrays were sometimes used as a substitute for variable-length argument lists to methods, which will be discussed. With the introduction of variablelength argument lists in Java, the usefulness of anonymous arrays has diminished.

The Java Language:Arrays:Using Arrays

The size of an array object is available in the public variable length:
 char [] alphabet = new char [26];  
 int alphaLen = alphabet.length; // alphaLen == 26  
 String [] musketeers = { "one", "two", "three" };  
 int num = musketeers.length; // num == 3  
length is the only accessible field of an array; it is a variable, not a method. (Don’t worry; the compiler tells you when you accidentally use parentheses as if it were a method, as everyone does now and then.) Array access in Java is just like array access in other languages; you access an element by putting an integer-valued expression between brackets after the name of the array. The following example creates an array of Button objects called keyPad and then fills the array with Button objects:
 Button [] keyPad = new Button [ 10 ];  
 for ( int i=0; i < keyPad.length; i++ )  
 keyPad[ i ] = new Button( Integer.toString( i ) );  
Remember that we can also use the enhanced for loop to iterate over array values. Here we’ll use it to print all the values we just assigned:
 for (Button b : keyPad)  
 System.out.println(b);  
Attempting to access an element that is outside the range of the array generates an ArrayIndexOutOfBoundsException. This is a type of RuntimeException, so you can either catch and handle it yourself if you really expect it, or ignore it, as we’ve already discussed:
 String [] states = new String [50];  
 try {  
 states[0] = "California";  
 states[1] = "Oregon";  
 ...  
 states[50] = "McDonald's Land"; // Error: array out of bounds  
 }  
 catch ( ArrayIndexOutOfBoundsException err ) {  
 System.out.println( "Handled error: " + err.getMessage() );  
 }  
It’s a common task to copy a range of elements from one array into another. One way to copy arrays is to use the low-level arraycopy() method of the System class:
 System.arraycopy( source, sourceStart, destination, destStart, length );  
The following example doubles the size of the names array from an earlier example:
 String [] tmpVar = new String [ 2 * names.length ];  
 System.arraycopy( names, 0, tmpVar, 0, names.length );  
 names = tmpVar;  
A new array, twice the size of names, is allocated and assigned to a temporary variable, tmpVar. The arraycopy() method is then used to copy the elements of names to the new array. Finally, the new array is assigned to names. If there are no remaining references to the old array object after names has been copied, it is garbage-collected on the next pass. An easier way is to use the java.util.ArrayscopyOf() and copyOfRange() methods:
 byte [] bar = new byte[] { 1, 2, 3, 4, 5 };  
 byte [] barCopy = Arrays.copyOf( bar, bar.length );  
 // { 1, 2, 3, 4, 5 }  
 byte [] expanded = Arrays.copyOf( bar, bar.length+2 );  
 // { 1, 2, 3, 4, 5, 0, 0 }  
 byte [] firstThree = Arrays.copyOfRange( bar, 0, 3 );  
 // { 1, 2, 3 }  
 byte [] lastThree = Arrays.copyOfRange( bar, 2, bar.length );  
 // { 3, 4, 5 }  
 byte [] lastThreePlusTwo = Arrays.copyOfRange( bar, 2, bar.length+2 );  
 // { 3, 4, 5, 0, 0 }  
The copyOf() method takes the original array and a target length. If the target length is larger than the original array length, then the new array is padded (with zeros or nulls) to the desired length. The copyOfRange() takes a starting index (inclusive) and an ending index (exclusive) and a desired length, which will also be padded if necessary.

The Java Language:Arrays:Array Creation and Initialization

The new operator is used to create an instance of an array. After the new operator, we specify the base type of the array and its length with a bracketed integer expression:
 arrayOfInts = new int [42];  
 someStrings = new String [ number + 2 ];  
We can, of course, combine the steps of declaring and allocating the array:
 double [] someNumbers = new double [20];  
 Component [] widgets = new Component [12];  
Array indices start with zero. Thus, the first element of someNumbers[] is 0, and the last element is 19. After creation, the array elements are initialized to the default values for their type. For numeric types, this means the elements are initially zero:
 int [] grades = new int [30];  
 grades[0] = 99;  
 grades[1] = 72;  
 // grades[2] == 0  
The elements of an array of objects are references to the objects—just like individual variables they point to—but do not actually contain instances of the objects. The default value of each element is therefore null until we assign instances of appropriate objects:
 String names [] = new String [4];  
 names [0] = new String();  
 names [1] = "Boofa";  
 names [2] = someObject.toString();  
 // names[3] == null  
This is an important distinction that can cause confusion. In many other languages, the act of creating an array is the same as allocating storage for its elements. In Java, a newly allocated array of objects actually contains only reference variables, each with the value null.6 That’s not to say that there is no memory associated with an empty array; memory is needed to hold those references (the empty “slots” in the array). Figure 4-4 illustrates the names array of the previous example.
names is a variable of type String[] (i.e., a string array). This particular String[] object contains four String type variables. We have assigned String objects to the first three array elements. The fourth has the default value null. Java supports the C-style curly braces {} construct for creating an array and initializing its elements:
 int [] primes = { 2, 3, 5, 7, 7+4 }; // e.g., primes[2] = 5  
An array object of the proper type and length is implicitly created, and the values of the comma-separated list of expressions are assigned to its elements. Note that we did not use the new keyword or the array type here. The type of the array was inferred from the assignment. We can use the {} syntax with an array of objects. In this case, each expression must evaluate to an object that can be assigned to a variable of the base type of the array or the value null. Here are some examples:
 String [] verbs = { "run", "jump", someWord.toString() };  
 Button [] controls = { stopButton, new Button("Forwards"),  
 new Button("Backwards") };  
 // All types are subtypes of Object  
 Object [] objects = { stopButton, "A word", null };  
The following are equivalent:
 Button [] threeButtons = new Button [3];  
 Button [] threeButtons = { null, null, null };  

The Java Language:Arrays:Array Types

An array type variable is denoted by a base type followed by the empty brackets, []. Alternatively, Java accepts a C-style declaration with the brackets placed after the array name. The following are equivalent:
 int [] arrayOfInts; // preferred  
 int arrayOfInts []; // C-style  
In each case, arrayOfInts is declared as an array of integers. The size of the array is not yet an issue because we are declaring only the array type variable. We have not yet created an actual instance of the array class, with its associated storage. It’s not even possible to specify the length of an array when declaring an array type variable. The size is strictly a function of the array object itself, not the reference to it. An array of reference types can be created in the same way:
 String [] someStrings;  
 Button [] someButtons;  

The Java Language: Arrays

An array is a special type of object that can hold an ordered collection of elements. The type of the elements of the array is called the base type of the array; the number of elements it holds is a fixed attribute called its length. Java supports arrays of all primitive and reference types. The basic syntax of arrays looks much like that of C or C++. We create an array of a specified length and access the elements with the index operator, []. Unlike other languages, however, arrays in Java are true, first-class objects. An array is an instance of a special Java array class and has a corresponding type in the type system. This means that to use an array, as with any other object, we first declare a variable of the appropriate type and then use the new operator to create an instance of it. Array objects differ from other objects in Java in three respects: • Java implicitly creates a special array class type for us whenever we declare a new type of array. It’s not strictly necessary to know about this process in order to use arrays, but it helps in understanding their structure and their relationship to other objects in Java later. • Java lets us use the [] operator to access array elements so that arrays look as we expect. We could implement our own classes that act like arrays, but we would have to settle for having methods such as get() and set() instead of using the special [] notation. • Java provides a corresponding special form of the new operator that lets us construct an instance of an array with a specified length with the [] notation or initialize it directly from a structured list of values.

The Java Language: Exceptions: Throwing Exceptions:Assertions:Using Assertions

An assertion enforces a rule about something that should be unchanging in your code and would otherwise go unchecked. You can use an assertion for added safety anywhere you want to verify your assumptions about program behavior that can’t be checked by the compiler. A common situation that cries out for an assertion is testing for multiple conditions or values where one should always be found. In this case, a failing assertion as the default or “fall through” behavior indicates the code is broken. For example, suppose we have a value called direction that should always contain either the constant value LEFT or RIGHT:
 if ( direction == LEFT )  
 doLeft();  
 else if ( direction == RIGHT )  
 doRight()  
 else  
 assert false : "bad direction";  
The same applies to the default case of a switch:
 switch ( direction ) {   
  case LEFT:   
  doLeft();   
  break;   
  case RIGHT:   
  doRight();   
  break;   
  default:   
  assert false;   
  }   
In general, you should not use assertions for checking the validity of arguments to methods because you want that behavior to be part of your application, not just a test for quality control that can be turned off. The validity of input to a method is called its preconditions, and you should usually throw an exception if they are not met; this elevates the preconditions to part of the method’s “contract” with the user. However, checking the correctness of results of your methods with assertions before returning them is a good idea; these are called post-conditions. Sometimes determining what is or is not a precondition depends on your point of view. For example, when a method is used internally within a class, preconditions may already be guaranteed by the methods that call it. Public methods of the class should probably throw exceptions when their preconditions are violated, but a private method might use assertions because its callers are always closely related code that should obey the correct behavior. Finally, note that assertions can not only test simple expressions but perform complex validation as well. Remember that anything you place in the condition expression of an assert statement is not evaluated when assertions are turned off. You can make helper methods for your assertions that may contain arbitrary amounts of code. And, although it suggests a dangerous programming style, you can even use assertions that have side effects to capture values for use by later assertions—all of which will be disabled when assertions are turned off. For example:
 int savedValue;  
 assert ( savedValue = getValue()) != -1;  
 // Do work...  
 assert checkValue( savedValue );  
Here, in the first assert, we use the helper method getValue() to retrieve some information and save it for later. Then, after doing some work, we check the saved value using another assertion, perhaps comparing results. When assertions are disabled, we’ll no longer save or check the data. Note that it’s necessary for us to be somewhat cute and make our first assert condition into a Boolean by checking for a known value. Again, using assertions with side effects is a bit dangerous because you have to be careful that those side effects are seen only by other assertions. Otherwise, you’ll be changing your application behavior when you turn them off.

The Java Language: Exceptions: Throwing Exceptions:Assertions:Enabling and Disabling Assertions

Assertions are turned on or off at runtime. When disabled, assertions still exist in the class files but are not executed and consume no time. You can enable and disable assertions for an entire application or on a package-by-package or even class-by-class basis. By default, assertions are turned off in Java. To enable them for your code, use the java command flag -ea or -enableassertions:
 % java -ea MyApplication  
To turn on assertions for a particular class, append the class name:
 % java -ea:com.allwareshare.examples.Myclass MyApplication  
To turn on assertions just for particular packages, append the package name with trailing ellipses (. . .):
 % java -ea:com.allwareshare.examples...MyApplication  
When you enable assertions for a package, Java also enables all subordinate package names (e.g., com.allwareshare.examples.text). However, you can be more selective by using the corresponding -da or -disableassertions flag to negate individual packages or classes. You can combine all this to achieve arbitrary groupings like this:
 % java -ea:com.allwareshare.examples...  
 -da:com.allwareshare.examples.text-ea:com.allwareshare.examples.text.MonkeyTypewriters  
 MyApplication  
This example enables assertions for the com.allwareshare.examples package as a whole, excludes the package com.allwareshare.examples.text, and then turns exceptions on for just one class, MonkeyTypewriters, in that package.

The Java Language: Assertions

An assertion is a simple pass/fail test of some condition, performed while your application is running. Assertions can be used to “sanity check” your code anywhere you believe certain conditions are guaranteed by correct program behavior. Assertions are distinct from other kinds of tests because they check conditions that should never be violated at a logical level: if the assertion fails, the application is to be considered broken and generally halts with an appropriate error message. Assertions are supported directly by the Java language and they can be turned on or off at runtime to remove any performance penalty of including them in your code. Using assertions to test for the correct behavior of your application is a simple but powerful technique for ensuring software quality. It fills a gap between those aspects of software that can be checked automatically by the compiler and those more generally checked by “unit tests” and human testing. Assertions test assumptions about program behavior and make them guarantees (at least while they are activated). If you have programmed before, you may have written something like the following:
 if ( !condition )  
 throw new AssertionError("fatal error: 42");  
An assertion in Java is equivalent to this example, but is performed with the assert language keyword. It takes a Boolean condition and an optional expression value. If the assertion fails, an AssertionError is thrown, which usually causes Java to bail out of the application. The optional expression may evaluate to either a primitive or object type. Either way, its sole purpose is to be turned into a string and shown to the user if the assertion fails; most often you’ll use a string message explicitly. Here are some examples:
 
assert false;
assert ( array.length > min );  
 assert a > 0 : a // shows value of a to the user  
 assert foo != null : "foo is null!" // shows message "foo is null!" to user  
In the event of failure, the first two assertions print only a generic message, whereas the third prints the value of a and the last prints the foo is null! message. Again, the important thing about assertions is not just that they are more terse than the equivalent if condition, but that they can be enabled or disabled when you run the application. Disabling assertions means that their test conditions are not even evaluated, so there is no performance penalty for including them in your code (other than, perhaps, space in the class files when they are loaded).

The Java Language: Exceptions: Throwing Exceptions:Try with Resources

A common use of the finally clause is to ensure that resources used in a try clause are cleaned up, no matter how the code exits the block.
 try {  
 // Socket sock = new Socket(...);  
 // work with sock  
 } catch( IOException e ) {  
 ...  
 }  
 finally {  
 if ( sock != null ) { sock.close(); }  
 }  
What we mean by “clean up” here is to deallocate expensive resources or close connections such as files, sockets, or database connections. In some cases, these resources might get cleaned up on their own eventually as Java reclaimed the garbage, but that would at best be at an unknown time in the future and at worst may never happen or may not happen before you run out of resources. So it is always best to guard against these situations. There are two problems with this venerable approach: first, it requires extra work to carry out this pattern in all of your code, including important things like null checks as shown in our example, and second, if you are juggling multiple resources in a single finally block, you have the possibility of your cleanup code throwing an exception (e.g., on close()) and leaving the job unfinished. In Java 7, things have been greatly simplified via the new “try with resources” form of the try clause. In this form, you may place one or more resource initialization statements within parentheses after a try keyword and those resources will automatically be “closed” for you when control leaves the try block.
 try (  
 Socket sock = new Socket("128.252.120.1", 80);  
 FileWriter file = new FileWriter("foo");  
 )  
 {  
 // work with sock and file  
 } catch ( IOException e ) {  
 ...  
 }  
In this example, we initialize both a Socket object and a FileWriter object within the try-with-resources clause and use them within the body of the try statement. When control leaves the try statement, either after successful completion or via an exception, both resources are automatically closed by calling their close() method. Resources are closed in the reverse of the order in which they were constructed, so dependencies among them can be accommodated. This behavior is supported for any class that implements the AutoCloseable interface (which, at current count, over 100 different built-in classes do). The close() method of this interface is prescribed to release all resources associated with the object, and you can implement this easily in your own classes as well. When using try with resources, we don’t have to add any code specifically to close the file or socket; it is done for us automatically. Another problem that try with resources solves is the pesky situation we alluded to where an exception may be thrown during a close operation. Looking back to the prior example in which we used a finally clause to do our cleanup, if an exception had been raised by the close() method, it would have been thrown at that point, completely abandoning the original exception from the body of the try clause. But in using try with resources, we preserve the original exception. If an exception occurs while within the body of the try and one or more exceptions is raised during the subsequent autoclosing operations, it is the original exception from the body of the try that is bubbled up to the caller. Let’s look at an example:
 try (  
 Socket sock = new Socket("128.252.120.1", 80); // potential exception #3  
 FileWriter file = new FileWriter("foo"); // potential exception #2  
 )  
 {  
 // work with sock and file // potential exception #1  
 }  
Once the try has begun, if an exception occurs as exception point #1, Java will attempt to close both resources in reverse order, leading to potential exceptions at locations #2 and #3. In this case, the calling code will still receive exception #1. Exceptions #2 and #3 are not lost, however; they are merely “suppressed” and can be retrieved via the Throwable getSuppressed() method of the exception thrown to the caller. This returns an array of all of the supressed exceptions.

The Java Language: Exceptions: Throwing Exceptions:The finally Clause

What if we have something important to do before we exit our method from one of the catch clauses? To avoid duplicating the code in each catch branch and to make the cleanup more explicit, you can use the finally clause. A finally clause can be added after a try and any associated catch clauses. Any statements in the body of the final ly clause are guaranteed to be executed no matter how control leaves the try body, whether an exception was thrown or not:
 try {  
 // Do something here  
 }  
 catch ( FileNotFoundException e ) {  
 ...  
 }  
 catch ( IOException e ) {  
 ...  
 }  
 catch ( Exception e ) {  
 ...  
 }  
 finally {  
 // Cleanup here is always executed  
 }  
In this example, the statements at the cleanup point are executed eventually, no matter how control leaves the try. If control transfers to one of the catch clauses, the statements in finally are executed after the catch completes. If none of the catch clauses handles the exception, the finally statements are executed before the exception propagates to the next level. If the statements in the try execute cleanly, or if we perform a return , break, or continue, the statements in the finally clause are still executed. To guarantee that some operations will run, we can even use try and finally without any catch clauses:
 try {  
 // Do something here  
 return;  
 }  
 finally {  
 System.out.println("Whoo-hoo!");  
 }  
Exceptions that occur in a catch or finally clause are handled normally; the search for an enclosing try/catch begins outside the offending try statement, after the fi nally has been executed.

The Java Language: Exceptions: Throwing Exceptions:try Creep

The try statement imposes a condition on the statements that it guards. It says that if an exception occurs within it, the remaining statements are abandoned. This has consequences for local variable initialization. If the compiler can’t determine whether a local variable assignment placed inside a try/catch block will happen, it won’t let us use the variable. For example:
 void myMethod() {
 int foo;
 try {
 foo = getResults();
 }
 catch ( Exception e ) {
 ...
 }
 int bar = foo; // Compile-time error: foo may not have been initialized
In this example, we can’t use foo in the indicated place because there’s a chance it was never assigned a value. One obvious option is to move the assignment inside the try statement:
 try {
 foo = getResults();
 int bar = foo; // Okay because we get here only
 // if previous assignment succeeds
 }
 catch ( Exception e ) {
 ...
 }
Sometimes this works just fine. However, now we have the same problem if we want to use bar later in myMethod(). If we’re not careful, we might end up pulling everything into the try statement. The situation changes, however, if we transfer control out of the method in the catch clause:
 try {
 foo = getResults();
 }
 catch ( Exception e ) {
 ...
 return;
 }
 int bar = foo; // Okay because we get here only
 // if previous assignment succeeds
The compiler is smart enough to know that if an error had occurred in the try clause, we wouldn’t have reached the bar assignment, so it allows us to refer to foo. Your code will dictate its own needs; you should just be aware of the options.