Java Intermediate 2

Description

Sample booklet for Java Intermediate2 ,which you can view and download for free.

Reviews
Shared by:
Anonymous
Stats
views:
332
downloads:
44
rating:
not rated
reviews:
0
posted:
11/12/2007
language:
English
pages:
0
CS108, Stanford Fall, 2005-06 Handout #5 Nick Parlante Java Intermediate 2 This is the quick review of intermediate Java material for our special Thu section. Topics on previous handout: packages, static, arrays. Files File Reading • Java uses input and output "stream" classes for file reading and writing -- the stream objects respond to read() and write(), and communicate back to the file system. InputStream and OuputStream are the most basic classes. • The streams objects are layered together to get the overall effect -- flexible but a bit cumbersome • The classes with "reader" or "writer" in the name deal with text files 1. FileReader -- knows how to read text chars from a file 2. BufferedReader -- buffers the text and makes it available line-by-line • For non-text data files (such as jpeg, png, mp3) use FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream -- these just deal with the file as a block of raw bytes. Common Text Reading Code // Classic file reading code -- the standard while/readLine loop // in a try/catch. public void echo(String filename) { try { // Create reader for the given filename BufferedReader in = new BufferedReader(new FileReader(filename)); // While/break to send readLine() until it returns null while (true) { String line = in.readLine(); if (line == null) { break; } // do something with line System.out.println(line); } in.close(); } catch (IOException except) { // The code above jumps to here on an IOException, // otherwise this code does not run. // Good simple strategy: print stack trace, maybe exit except.printStackTrace(); // System.exit(1); // could do this too } } 2 // the loop can be written as "while ((line=in.readLine()) != null) {" Exceptions An exception occurs at runtime when a line of code tries to do something impossible such as accessing an array using an index number that is out of bounds of the array or dereferencing a pointer that is null. We have seen exceptions like that interrupt our programs many times as we debug our code. We must deal with exceptions a little in our file-reading code since the code can run into some real error conditions, such as when the file want to read is not there. An exception halts the normal progress of the code and searches for some error handling code that matches the exception. Most often, the error handling code will print some sort of warning message and then possibly exit the program, although it could take some more sophisticated corrective action. Java uses a "try/catch" structure to position error-handling code to be used in the event of an exception. The main code to run goes in a "try" section, and it runs normally. If any line in the try section hits an exception at runtime, the program looks for a "catch-block" section for that type of exception. The normal flow of execution jumps from the point of the exception to the code in the catch-block. The lines immediately following the point of the exception are never executed. normal code progress on exception, execution jumps to the catch block try { stmt(); stmt(); stmt(); stmt(); } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } For the file-reading code, some of the file operations such as creating the FileReader, or calling the readLine() method can fail at runtime with an IOException. For example, creating the FileReader could fail if there is no file named "file.txt" in the program directory. The readLine() could fail if, say, the file is on a CD ROM, our code is halfway through reading the file, and at that moment our pet parrot hits the eject button and flies off with the CD. The readLine() will soon throw an IOException since the file has disappeared midway through reading the file. 3 Our file-reading method will use a simple try/catch pattern for exception handling. All the filereading code goes inside the "try" section. It is followed by a single catch-block for the possible IOException. The catch prints an error message using the built-int method printStackTrace(). The "stack trace" will list the exception at the top, followed by the method-file-line where it occurred, followed by the stack of earlier methods that called the method that failed. In the example stack trace below, the method hide() in the Foo class has failed with a NullPointerException. The offending line was line 83 in the file Foo.java. The hide() method was called by main() in FooClient on line 23. java.lang.NullPointerException at Foo.hide(Foo.java:83) at FooClient.main(FooClient.java:23) In production code, the catch will often exit the whole program, using a non-zero int exit code to indicate a program fault (e.g. call System.exit(1)). Alternately, the program could try to take corrective action in the catch-block to address the situation. Avoid leaving the catch empty -- that can make debugging very hard if the error happens at runtime, but is swallowed up. Just put a printStackTrace() in the catch so you know what happened. If no exception occurs during the run, the catch-block is ignored; the catch is only used in the event of an exception. Collection Classes • Built-in classes for common storage problems (like the C++ Standard Template Library STL) -called the "collection classes" overall. • We'll concentrate on the two most important collection implementation classes: ArrayList and HashMap • "Collection" interface -- top level interface (most broad) for storage of collection of things • Two main subinterfaces of Collection: - "List" -- a collection of elements in a particular order, like an array. Can refer to elements by a numeric index 0, 1, 2, and so on. - "Set" -- a collection elements as a set, without duplication • "Map" interface -- hash table type key/value storage, with fast lookup by key. (Map is not a subinterface of Collection, it's more of a sibling of Collection). • The collections only store Object pointers, not primitives. • See the Sun docs: http://java.sun.com/docs/books/tutorial/collections/ "Raw" Collection Style • The first version of the Collection classes stores all the client data in the form of Object pointers (like storing everything as a void*). The client code has to put in casts to cast the Object pointer back to its true type (the JVM checks the cast at runtime). • This style is now knows as the "raw" style compared to Java 5 generics. The raw use continues to work and can still be appropriate. The generic style is described below, after the coverage of the raw style. 4 Collection Design • As much as possible, the various collection classes use the same method names (e.g. add(), iterator(), ...), so you can change client code to use a different type of collection with little or zero client code change. • The collection classes only store pointers to objects. They cannot store primitives directly. - To store a primitive, such as an int, put the int value in a wrapper object (Integer, Double, …) and store the wrapper object. - e.g. given an int i that we want to store in a list... - Integer intObj = new Integer(i); - list.add(intObj); - intObj.intValue() // gets the int value from the object • In the source code, collections store all pointers as type Object (like void*), so you cast the pointer back to what it really is, such as String, when extracting the pointer from the collection. • At runtime, java checks all casts, so a bad cast will be caught at that time. Collection Messages • There are a few basic methods, and most of the higher-level capabilities are built on them. • constructor -- create a collection with no elements - Actually, a Java interface cannot specify a ctor or static method, but all the collection classes implement the default, zero-argument ctor at a minimum. • int size() -- number of elements in the collection - This could have been called getSize() or getLength(), but they kept the name size() to remain compatible with the old Vector class. • boolean add(Object ptr) - Add a new pointer/element to the collection. Adds to the "end" for collections that have an ordering. Returns true if the collection is modified (it might not be when adding to a Set type collection). - The Set uses equals() to decide if the element is the same as an existing element • iterator() - Return a new Iterator object set up to iterate through the collection and possibly remove elements. Collection Utilities • Utilities -- these convenience methods are built on top of the basic methods above. See the Collection interface for the complete list. • boolean isEmpty() -- true if the collection is empty • boolean contains(Object obj) -- search for the given element -- uses equals() on the elements (O(n) for an ArrayList) • boolean remove(Object obj) -- search and remove if found -- uses equals() on the elements (O(n) for an ArrayList) • boolean addAll(Collection coll) -- adds all of the elements in given collection to the receiver (true if changed) • boolean removeAll(Collection coll) -- removes all of the elements in the given collection from the receiver (true if changed) 5 Iterator • An Iterator object allows the client to see each element in a collection • The Iterator interface provides a uniform way to iterate over the elements in many different types of collection • "Iterator" is the general type of iterator. It has a subclass, ListIterator, with insert/delete capabilities appropriate for List type collections. • Iterator messages: - -hasNext() -- returns true if more elements, - -next() returns the Object pointer of the next element - -remove() -- (optional) removes the element returned by the previous call to next(). It is only valid to call remove() after a call to next(). Note that this is potentially much more efficient than the collection.remove() message, since the element location within the collection is already known by the iterator. • To use an iterator: create the iterator object, then in a loop call hasNext() and next() to see all the elements. - e.g. to iterate over "list"... - Iterator it = list.iterator(); - while (it.hasNext()) { - // do something with it.next(); - } • The above can also be written using a for-loop • It is valid to have multiple iterators going over a collection at once, so long as the collection does not change structurally -- no adds or removes of elements. • If a collection changes during iteration, then there can only be a single iterator, and the change must be through that iterator. During iteration, do not call collection.add() or collection.remove(). During iteration, it is ok to change the collection through the iterator itself, such as with iterator.remove(). Such invalid changes the collection during iteration may give a ConcurrentModificationException. List Interface • The "List" interface, is a subinterface (like a subclass) of Collection. List has a 0..length-1 ordering of the elements. • The ArrayList is the most commonly used List. LinkedList is the other, with better insert/delete performance. For most problems, ArrayList gives the best performance. • In addition to the basic Collection, supports messages for adding, inserting, and removing elements by their index number... • add(int index, Object obj) -- insert the object at the given index • remove(int index) -- remove the object at the given index • set(int index, Object obj) -- replace the pointer at the given index with the given pointer ArrayList • • • • • Popular "List" type collection Replaces the old "Vector" class -- like an array, but it can grow over time add() -- add pointer to end of the collection int size() -- number of elements Object get(int index) -- retrieve the elem pointer, indexed (0..len-1) 6 • iterator() -- return an iterator object to iterate over the array list - Responds to hasNext(), next() and remove() as above ArrayList/HashMap Example Code // Shows basic use of the ArrayList and iterators // with the classic pre-template style. public static void demoList1() { List a = new ArrayList(); a.add("Don't"); a.add("blame"); a.add("me"); // access the length System.out.println("size:" + a.size()); // 1. iterate using iterator Iterator it = a.iterator(); while (it.hasNext()) { // use next() to get elem, cast to its true class String string = (String)it.next(); System.out.println(string); } // 2. iterate using for/get/index (like an array) // (this works for List, not for Collection) for (int i=0; i shallow = Arrays.asList(array); // Add/remove will fail on the list -- it's really just using // the fixed size array // Make a new ArrayList using those elements // (constructor really allocates a whole new ArrayList) List colors = new ArrayList(shallow); System.out.println("colors " + colors); // uses toString System.out.println("size " + colors.size()); // 6 System.out.println("ochre " + colors.contains("ochre")); // true 9 System.out.println("index " + colors.indexOf("ochre")); colors.remove("ochre"); System.out.println("remove ochre " + colors); List colors2 = Arrays.asList(new String[] {"stripes", "polka dots", "purple" } ); System.out.println("colors2 " + colors2); colors.addAll(colors2); // adds them all System.out.println("add all colors2 " + colors); colors.removeAll(colors2); System.out.println("remove all colors2 " + colors); // subList -- make a shallow List showing just part of the original // shows elements 0, 1, 2 List front = colors.subList(0, 3); System.out.println("front " + front); // can make changes through front // (do not make changes to colors while using front) front.contains("green"); front.remove("green"); front.add("fire"); // they are reflected in underlying list System.out.println("colors " + colors); // Collections has static min/max/sort, and lots of others System.out.println("min " + Collections.min(colors)); System.out.println("max " + Collections.max(colors)); // Sort the whole thing Collections.sort(colors); System.out.println("sort " + colors); // Make an umodifiable wrapper -- could pass to some other code List noMod = Collections.unmodifiableList(colors); noMod.add("foo"); // throws an exception // // // // // // // // // // // } Output: colors [red, green, blue, yellow, ochre, purple] remove ochre [red, green, blue, yellow, purple] colors2 [stripes, polka dots, purple] add all colors2 [red, green, blue, yellow, purple, stripes, polka dots, purple] remove all colors2 [red, green, blue, yellow] front [red, green, blue] colors [red, blue, fire, yellow] min blue max yellow sort [blue, fire, red, yellow] // 4 } Java Generics Java generics have two flavors -- there are some uses of generics that are simple to understand and clearly make the code cleaner. Then there are advanced ways to use generics that I find really hard to follow, and I'm not convinced they are really worth using. For the start of CS108, we will concentrate on the few, most mainstream uses of templates, and we may play with the more esoteric uses later in the quarter. 10 Three Uses • Here are the three use patterns of generics that I think work for most situations (details below)… • 1. Using a template class, like ArrayList • 2. Writing template code with a simple type parameter • 3. Writing template code with a type parameter Use Template Class • Many Java library classes have been made generic, so instead of raw Object, they can be used in a way that indicates the type of object they hold. • For example, create an ArrayList that holds Strings as shown below. Both the variable holding the pointer and the call to the constructor have added. ArrayList list = new ArrayList(); list.add("hi"); list.add("there"); String s = list.get(0); //; no cast required! • The advantage is that now we don't have to put in the (String) cast -- uses of the list already know that they contain String, and compile time type checking can use that fact. • The iterator is now type Iterator. • Can assign back and forth between generic and raw versions, and it works. It may give a warning. At runtime, all the casts are checked in any case, so if the wrong sort of object gets into a List it will be noticed at runtime. Boxing/Unboxing • Normally, you cannot store an int or a boolean in an ArrayList, since it can only store Object pointers. • With Java 5 boxing, when the code needs an Integer but has an int, it automatically creates the Integer on the fly, without requiring anything in the source code. Going the other direction, if the code has an Integer but needs an int, it automatically calls intValue() on the integer to get the value. • This works for all the primitives -- int, char double, boolean, … • This works especially well with generic collections, which know that they contain Integer or whatever. New Foreach Loop • One the most likeable new features in Java 5 is a simple enhancement to the for-loop that iterates over any collection or array… List strings = ... for (String s: strings) { System.out.println(s); } 11 • This is a shorthand for looping over the elements, as would be done by an iterator. The fancy iterator features -- such as remove() -- are not present. You also do not have access to the index number. • Nonetheless, this syntax is very handy for the very common case of iterating over a collection of anything. Template Use Example Code // Shows basic use of the ArrayList and iterators // with the generics. public static void demoList() { // ** Create a List List a = new ArrayList(); a.add("Don't"); a.add("blame"); a.add("me"); // ** Instead of Iterator, make an Iterator Iterator it = a.iterator(); while (it.hasNext()) { // NOTE: no cast required here -- it.next() is a String String string = it.next(); System.out.println(string); } // ** Likewise, can make a List List ints = new ArrayList(); for (int i=0; i<10; i++) { ints.add(new Integer(i * i)); } // No casts needed here -- it knows they are Integer int sum = ints.get(0).intValue() + ints.get(1).intValue(); // With auto Unboxing, can just write it like this... sum = ints.get(0) + ints.get(1); // Can go back and forth between typed Collections and untyped "raw" // forms -- may get a warning. List genList = new ArrayList(); // warning List rawList = new ArrayList(); // no warning rawList.add("hello"); genList = rawList; rawList = genList; // warning // no warning } public static void demoMap() { // ** Make a map, specifying both key and value types HashMap map = new HashMap(); // Map Integers to their words map.put(new Integer(1), "one"); map.put(new Integer(2), "two"); map.put(3, "three"); // Here, just let the auto boxing make the Integer map.put(4 , "four"); String s = map.get(new Integer(3)); // returns type String // map.put("hi", "there"); // NO does not compile // ** Auto unboxing -- converts between Integer and int 12 Integer intObj = new Integer(7); int sum = intObj + 3; // intObj unboxes automatically to an int, sum is 10 // ** More complex example -- map strings to lists of Integer HashMap> counts = new HashMap>(); List evens = new ArrayList(); evens.add(2); evens.add(4); evens.add(6); counts.put("evens", evens); // Get the List back out... List evens2 = counts.get("evens"); sum = evens2.get(0) + evens2.get(1); // unboxing here, sum is 6 } Define Generic Class • You can define your own class as a generic class -- where it is parameterized by a type chosen by the client, typically called . This is more or less what ArrayList does. • The simplest form of this is where the class code doe not have any specific constraint on what the T type is. The only things we do with T are: - declare variables, parameters, and return types of that type - use = on its pointers - call methods that work on all Objects, like .equals() Generic Class Example Code /* Generic "T" class -- define a class parameterized by one or more "T" types. The class does not depend on any feature of the T type -just uses "=" to store and return its pointers. The T type can be used for parameters and return types. This approach is quite easy to do, and solves all the cases where we don't really care about the T type. This is basicaly how ArrayList and HashMap do it. */ public class Pair { private T a; private T b; public Pair(T a, T b) { this.a = a; this.b = b; } public T getA() { return a; } public T getB() { return b; } public void swap() { T temp = a; // NOTE T temporary variable a = b; b = temp; 13 } // True if a and b are the same public boolean isSame() { return a.equals(b); // NOTE Can only do things on T vars that work on any Object } // True if a or b is the given object // NOTE: use of T as a parameter public boolean contains(T elem) { return (a.equals(elem) || b.equals(elem)); } private void doesNotWork(Object x) { // T var = new T(); // NO, T not real at runtime // T[] array = new T[10]; } // T temp = (T) x; // NO, same reason // NO, same reason public static void main(String[] args) { // ** Make a Pair of Integer Pair ipair = new Pair(1, 2); Integer a = ipair.getA(); int b = ipair.getB(); // ** Also make a Pair of String Pair spair = new Pair("hi", "there"); String s = spair.getA(); // boolean ok = (ipair.getA() == spair.getA()); // NO does not compile, // Integer and String not the same type } } Container Anomaly • There is a basic problem between the type of a container and the type of thing it contains. • A variable of type List cannot point to a List -- this is very unintuitive, but it is a real constraint. Container Anomaly Example Code } public static void problem() { Object o; String s = "hello"; o = s; // fine public static void doSomething(List lo) { List lo = new ArrayList(); List ls = new ArrayList(); // lo = ls; // NO does not compile 14 // this would be a big prob if above were allowed lo.add(new Integer(3)); // doSomething(ls); // // // // // // NO same problem The point: you can assign a pointer of type sub to a pointer of type super. However, you cannot assign a pointer type container(sub) into a pointer of type container(super). Therefore Collection will not work as a sort of catch-all type for any sort of collection. } // Question: what sort of collection parameter allows us to // pass in any sort of collection. Collection is not it. Solve Anomaly We cannot use List as a catch-all to point to any sort of List. How to solve this? There are three solutions (examples of all these below) 1. Use a parameterization on the method. 2. Use a "don't care" wildcard parameterization -- simpler than and we lose the ability to use T type as a parameter or other type. If we truly don't care, then this works great and is simple. This is my preferred technique where at all possible. • 3. Use variant, where we don't care what the type is, so long as it is a subclass of Foo. This is the "bounded wildcard". • • • • • Solve Anomaly Example Code // Solution 1 - use a type on the method to // identify what type of element is in the collection. // The goes just before the return type. // This is ok, but slightly heavyweight, since really // we just don't care what type of thing is in there. public static void removeAdjacent(Collection coll) { Iterator it = coll.iterator(); T last = null; while (it.hasNext()) { T curr = it.next(); if (curr == last) it.remove(); last = curr; } } // Solution 2 -- Use a "wildcard" on the parameter, which // is basically a "don't care" marker. This is simpler than . public static void countAdjacent2(Collection coll) { Iterator it = coll.iterator(); Object last = null; while (it.hasNext()) { Object curr = it.next(); // Can put the ? thing in an Object if (curr == last) it.remove(); last = curr; } } // Here's an example where we take in two collections. // We can access the elements in each collection as Object. // Returns true if the two collections have any elements in common. 15 public static boolean haveCommon(Collection a, Collection b) { for (Object o: a) { if (b.contains(o)) return true; } return false; } // Here's an example where, rather than Collection, the "extends" // adds a constraint that the elements must be subclasses of Number. public static int sumAll(Collection nums) { int sum = 0; for (Number n:nums) { sum += n.intValue(); } return sum; } // Here we see that sumAll() works for various collections // of Number subclasses. public static void callSum() { List ints = new ArrayList(); ints.add(1); ints.add(2); int sum = sumAll(ints); // works! List dubs = new ArrayList(); dubs.add(1.0); dubs.add(2.0); int sum2 = sumAll(dubs); // works! }
Related docs
Pengenalan Bahasa JAVA
Views: 242  |  Downloads: 21
CS0401 COE0401 Intermediate Java Programming
Views: 0  |  Downloads: 0
Java-in-XML
Views: 41  |  Downloads: 6
JAVA
Views: 129  |  Downloads: 0
COP3804 - Intermediate Java Programming(1)
Views: 0  |  Downloads: 0
COP3804 - Intermediate Java Programming
Views: 0  |  Downloads: 0
Java 2 certification guide
Views: 634  |  Downloads: 48
intermediate level programming (am38)
Views: 2  |  Downloads: 0
Java Overview
Views: 5  |  Downloads: 0
JAVA SOLUTION
Views: 20  |  Downloads: 2
JAVA
Views: 179  |  Downloads: 33
Important java programs with solution
Views: 94  |  Downloads: 14