Java Fundamentals
Fundamental language mechanisms
The exception mechanism
What are exceptions? Exceptions are exceptional events in the execution of a program Depending on how grave the event is, the program might or might not recover From a programming standpoint, exceptions are also classes through which such events are represented In Java exceptions are objects
Why use exceptions? Separation of the error handling code Cleaner program structure Possibility to easily trace the cause of the event (propagation through the call stack) In some cases, possibility to continue execution (after handling the unpredicted event) Easier management of rare resources (e.g. files, connections)
The old approach 1. if(!db_connect()){ 2. //return error 3. } 4. int error_code = do_db_op(); 5. switch(error_code){ 6. //handle error 7. } 8. //etc.
The new approach 1. try { 2. conn = DriverManager.getConnection( ); 3. stmt = conn.createstatement(); 4. int result = stmt.executeupdate( "); 5. catch (SQLException ex) { 6. //handle exception 7. }
Types exceptions in Java Checked exceptions are exceptions from which the program can and should recover (e.g. a file is not found) must be handled, either by catching or throwing Errors are exceptional events from outside the application, from which it cannot usually recover (e.g. a hardware component fails)
Types exceptions in Java Runtime exceptions are generated within the application but cannot usually be recovered from (i.e. a null pointer is sent to a constructor) not necessarily handled
Exception handling try - a block defining the code to be checked catch - a block treating an exception there can be multiple catch blocks catch blocks for an exception are selected sequentially catch blocks should be defined from the specific to the general finally - a block executed whether exceptions are raised or not
Exception handling 1. try { 2. //code 3. } catch (Exception1 ex) { 4. //handle first type of exception 5. } catch (Exception2 ex) { 6. //handle second type of exception 7. // 8. } finally { 9. //execute regardless if exceptions were thrown 10. }
Reading exception output Call stack Stack trace
Handling resources Finally blocks Always dispose of resources in finally Avoid nesting try blocks in finally Try with resources (only in Java 7)
Handling resources 1. try { 2. writer = new FileWriter(f); 3. } catch (IOException ex) { 4. ex.printstacktrace(); 5. } 6. finally{ 7. if (writer!=null) 8. writer.close(); 9. }
Throwing exceptions Exception forwarding Checked exceptions should be handled by the code which can restore the normal flow of the application The throws clause Throwing exceptions The throw instruction Custom exception classes
Function throwing an exception 1. public int checkaccount() throws IOException{ 2. // 3. } Page 16 7/22/2011
Stream based I/O
Why streams Standardized method of access Destinations or sources have the same interface Possibility of piping Hides complexity of operations
Stream piping Stream piping allows for the chaining of streams Byte, character and buffered streams can be chained to hide complexity
Piped streams 1. FileWriter writer = null; 2. PrintWriter out; 3. // 4. writer = new FileWriter(f); 5. out = new PrintWriter(writer); 6. out.println("sometext");
Available streams Byte, character and buffered streams Standard input System.in System.out System.err Console
Using buffered streams 1. BufferedReader in = null; 2. PrintWriter out = null; 3. in = new BufferedReader(new FileReader("test.in")); 4. out = new PrintWriter (new FileWriter("test.out")); 5. String l; 6. while ((l = in.readline())!= null) { 7. out.write(l); 8. }
Scanning and formatting Scanners extract tokens from input data tokens can be of string type, but also primitive types Formatters the format method outputs data according to a format string http://download.oracle.com/javase/7/docs/api/j ava/util/formatter.html#syntax
Using a scanner 1. Scanner scanner = null; 2. scanner = new Scanner(new BufferedReader(new FileReader("numbers.txt"))); 3. while (scanner.hasnext()) { 4. if (scanner.hasnextint()) { 5. System.out.println(scanner.nextInt()); 6. } else { 7. scanner.next(); 8. } 9. }
Other streams Data streams Can read typed values from a file Reading ends based on an EOFException, not a return value
Other streams Object streams Objects can be written and read from a file as long as they are serializable The possibility to serialize is marked through the Serialize interface Objects which contain references to local resources(e.g. a connection) are not serializable
Using object strems 1. ObjectOutputStream penguinstream = null; 2. ObjectInputStream clonestream = null; 3. // 4. penguinstream = new ObjectOutputStream(new FileOutputStream("penguins.db")); 5. penguinstream.writeobject(somepenguin); 6. clonestream = new ObjectInputStream(new FileInputStream("penguins.db")); 7. Penguin someclone = (Penguin) clonestream.readobject();
Generics
What are generics? Syntactic mechanism Allow for the definition of generic code
Why use generics It is preferable to detect errors at compile time Code using Object can be confusing and difficult to maintain Easier implementation of containers and thus collections
A simple container 1. public class Nest { 2. public Object content; 3. public void addcontent(object content){ 4. this.content = content; 5. } 6. public Object getcontent(){ 7. return content; 8. } 9. }
The problem with containers 1. Duckling smallduck = new Duckling("quacky"); 2. Nest nest = new Nest(); 3. nest.addcontent(smallduck); 4. //every time we want to access it we must cast it 5. //and know what the right type is 6. Duckling copyduck = (Duckling) nest.getcontent();
Using generics Generics define a template Generic types are replaced with actual types Using an incompatible type generates compile time errors While Box<String> and Box<Integer> are incompatible at compile time, they have the same type at runtime
A generic nest 1. public class Nest<T> { 2. public T content; 3. public void addcontent(t content){ 4. this.content = content; 5. } 6. public T getcontent(){ 7. return content; 8. } 9. }
The advantage of a generic nest 1. Duckling smallduck = new Duckling("quacky"); 2. Nest<Duckling> nest = new Nest<Duckling>(); 3. nest.addcontent(smallduck); 4. //no more casting to Duckling 5. Duckling copyduck = nest.getcontent();
What can generics be used for? Generic functions Generic classes Generic constructors
More generics Type rewriting Generic bounded types Upper bounded Lower bounded Generic wildcards
Using type binding 1. public class Nest<T extends Flying> { 2. // 3. } 4. //the nest can contain only children of Flying
Collections
What are collections? A collection is a group of single elements of a certain type Elements can be considered containers for a single object Initially collections contained objects of Object type Generic collections are collections with elements of a specified type
Why use collections? Arrays are difficult to use fixed length space inefficient it is difficult to delete elements it is difficult to represent higher complexity structures (e.g. a queue) Collections have evolved from design patterns used on arrays
Declaring a collection 1. Animal lion = new Animal("lion"); 2. Animal dog = new Animal("dog"); 3. ArrayList list = new ArrayList(); 4. list.add(lion); 5. list.add(dog);
Iterating a collection with foreach 1. for (Object item : list) { 2. Animal currentanimal = (Animal)item; 3. currentanimal.makesound(); 4. }
A generic collection 1. Animal lion = new Animal("lion"); 2. Animal dog = new Animal("dog"); 3. List<Animal> list = new ArrayList<Animal>(); 4. list.add(lion); 5. list.add(dog); 6. for (Animal item : list) { 7. item.makesound(); 8. }
The Collection framework Interfaces abstract types outlining the various categories of collections Implementations actual implementations of the interfaces user defined implementations can be added Algorithms polymorphic implementations of useful collection operations such as sorting
Core collection interfaces Collection Set SortedSet List Queue Map SortedMap
Iterators Collections can be easily manipulated with the foreach language construct Iterators are special objects used to traverse a collection Iterator methods next hasnext remove Iterators are the only safe way to delete elements from collections
Using an iterator 1. for (Iterator<Road> it = roads.iterator(); 2. it.hasnext();) { 3. Road road = it.next(); 4. if (road.name.equals("dacia")) { 5. it.remove(); 6. continue; 7. } 8. System.out.println(road.name); 9. }
Set implementations sets contain unique elements general implementations HashSet is a faster implementation but does not support ordering; has a fixed initial capacity which affects iteration time TreeSet also implements sorted set, although it is slower LinkedHashSet is a n intermediary implementation with support for insert ordered iteration
Set implementations special purpose implementations EnumSet is a high performance implementation usable with enum types CopyOnWriteArraySet implements a set which makes a new copy for any operation which modifies it (insert,delete,update); this is the only intrinsically thread safe set
List implementations Lists are ordered collections and as such support positional operations Lists can contain duplicate elements General purpose implementations ArrayList supplies fast, constant time positional access LinkedList is a list optimized for deletion and full iteration Special purpose implementations CopyOnWriteArrayList implements a list which makes a new copy for any operation which
Queue implementations Queues are collections which have added operations A queue can be treated as the titular structure or as a simple collection
Queue implementations Generic implementations PriorityQueue is an implementation providing ordering either based on a Comparator LinkedList is also an implementation of Qu Concurrent implementations LinkedBlockingQueue,ArrayBlockingQueue,Prior ityblockingqueue,delayqueue,synchronousque ue
Map implementations Maps are collections of key/value pairs General purpose implementations HashMap provides maximum performance but is not sorted TreeMap provides operations specific to sorted maps LinkedHashMap provides key access ordering (pairs are ordered in according to the latest access to their key)
Map implementations Special purpose implementations EnumMap is a high performance implementation for use with enum keys WeakHashMap is an implementation optimized for garbage collection keys are stored as weak references pairs are collected when no longer referenced from outside the map IdentityHashMap maintains knowledge of which objects have been seen and which have not Concurrent maps ConcurrentMap is a map optimized for
Using a map 1. Map<String,String> dictionary = 2. new HashMap<String, String>(3); 3. dictionary.put("cat", "cat definition"); 4. dictionary.put("dog", "dog definition"); 5. dictionary.put("penguin", "penguin definition"); 6. dictionary.put("duck", "duck definition"); 7. for (Entry<String,String> item : 8. dictionary.entryset()) { 9. System.out.println("Definition for " + 10. item.getkey() + " is " + item.getvalue()); 11. }
Wrapper implementations Wrapper implementations use a specified collection for their operations but add functionality synchronized versions of the collections e.g. Collection.synchronizedList unmodifiable versions of the collections e.g. Collection.unmodifiableList
What implementations to use? Commonly used implementations: ArrayList for List HashSet for Set LinkedList for Queue HashMap for Map
Algorithms Reusable algorithms static methods polymorphic Found in the Collections class
Available algorithms Sorting sort Shuffling shuffle Common operations reverse fill copy swap addall
Available algorithms Searching binarysearch Composition frequency disjoint Extreme values min max
Using algorithms Most algorithms assume the existence of a way of comparing objects A class which wishes to be compared can do so in two ways Via a defauld comparator Via a custom comparator
Using the default comparator The default comparator is used by implementing the Comparable interface which forces a class to implement compareto compareto returns a numeric value reflecting ordering
A comparable class 1. public class Penguin implements 2. Comparable<Penguin>{ 3. String name; 4. int speed; 5. // 6. public int compareto(penguin o) { 7. return this.speed - o.speed; 8. } 9. 10. }
Sorting a collection 1. List<Integer> list = new ArrayList<Integer>(); 2. //add the values 3. Collections.sort(list); 4. for (Integer item : list) { 5. //process each item 6. }
Using a custom comparator A custom comparator is a separate class It must implement the generic Comparator<ClassToBeCompared> interface which forces the implementation of the compare method The compare method returns a similar result to compareto(and can in fact use it)
A custom comparator 1. public class PenguinComparator implements 2. Comparator<Penguin>{ 3. public int compare(penguin o1, Penguin o2) { 4. return o1.name.compareto(o2.name); 5. } 6. }
Searching the collection 1. //binary search needs a form of comparisson 2. int index = Collections.binarySearch(penguinList, new Penguin("A", 0), new PenguinComparator());