Java for C++ Programmers Second Night Overview • First Night – Basics – Classes and Objects • Second Night – Enumerations – Exceptions – Input/Output – Templates vs. Generics – STL vs. JavaSE API Second Night Agenda • Enumerations, Exceptions, Input/Output – enumeration declaration & usage, exception hierarchy, checked vs. unchecked exceptions, throwing & catching exceptions, scanner class, console I/O, file I/O – Discussion – Lab exercises • Break • Templates vs. Generics, STL vs. JavaSE API – – Discussion – Lab exercises Enumerated Values in C++ • One way to define a set of enumerated values/constants in C++ is as follows… const const const const int int int int CLUBS = 0; DIAMONDS = 1; HEARTS = 2; SPADES = 3; • Example usage… // good invocations DrawSuit(CLUBS); DrawSuit(HEARTS); void DrawSuit(int s) { // draws the suit in a GUI } Enumerated Values in Java • Here’s the Java port of that C++ code… public class Suit public static public static public static public static } { final final final final int int int int CLUBS = 0; DIAMONDS = 1; HEARTS = 2; SPADES = 3; • Everything looks good, right? // good invocations drawCard(Suit.CLUBS); drawCard(Suit.DIAMONDS); static void drawCard(int s) { // draws the suit in a GUI } Enumerated Values in Java • Well, sort of – as long as the user behaves themselves… // bad invocations drawCard(Suit.HEARTS * 5); drawCard(-516); static void drawCard(int s) { // draws the suit in a GUI } • Using something unbounded like an int or a String can be problematic, need to restrict the available choices Enumerations in Java • Thankfully, there’s a better way to enumerate a set of values, staring in Java 5 there is an enumerated type – Similar to enum construct in C/C++ – Enums are declared similarly to classes public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES } Enumerations in Java • Now, each constant is strongly typed • When something is expecting a suit, we specify a Suit enum type • Invalid usage is now caught at compile time // good invocations drawCard(Suit.CLUBS); drawCard(Suit.DIAMONDS); // compiler errors drawCard(Suit.HEARTS * 5); drawCard(-516); static void drawCard(Suit s) { // draws the symbol for the suit in a GUI } Enumerations in Java • Additionally, we can switch on enums… // draws the symbol for the suit in a GUI static void drawCard(Suit s) { switch(s) { case CLUBS: case SPADES: // switch color to black, then draw break; default: // switch color to red, then draw break; } } Enumerations in Java • We can also give enums in Java additional members and methods public enum Planet { VENUS(4.8685e24,6051.8e3), EARTH(5.9736e24,6378.1e3), MARS(0.64185e24,3397e3); public static final double G = 6.67300E-11; final double mass; final double radius; Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } double surfaceGravity() { return G * mass / (radius * radius); } double surfaceWeight(double otherMass) { return otherMass * surfaceGravity(); } } Enumerations • Example usage, similar to a class… // acceptable usage drawPlanet(Planet.EARTH); System.out.println("Surface gravity on earth: "); System.out.println(Planet.EARTH.surfaceGravity()); • But we get compiler errors, if we try to construct more… // compiler errors Planet.EARTH = new Planet(1.0, 1.0); Planet p = new Planet(1.0, 1.0); Exceptions in C++ • C++ allows us to throw anything as an exception • Here is a modified factorial function which throws the number back if it is less than 0 int factorial(int n) { // check for exceptional case if(n < 0) { throw n; } // computation for normal case int result = 1; for(int i = n; i > 0; i--) { result *= i; } return result; } Exceptions in C++ • Example catching of that exception in C++… int main(int argc, char** argv) { int num = -4; try { cout << "factorial(" << num << "): " << factorial(num) << endl; } catch(int i) { cerr << i << " is not valid" << endl; } return 0; } Exceptions in C++ • We can also throw more complex types, for example, here is a custom exception class which stores an error message… class Exception { private: string m_message; public: Exception(string message) : m_message(message) { }; string GetMessage() { return this->m_message; }; }; Exceptions in C++ • Factorial function modified to throw custom exception type… int factorial(int n) { // check for exceptional case if(n < 0) { throw Exception("number must be positive"); } // computation for normal case int result = 1; for(int i = n; i > 0; i--) { result *= i; } return result; } Exceptions • Example catching of that exception in C++… int main(int argc, char** argv) { int num = -4; try { cout << "factorial(" << num << "): " << factorial(num) << endl; } catch(Exception e) { cerr << e.GetMessage() << endl; } return 0; } Exceptions in Java • In Java, we cannot throw primitives or most objects • Anything that is thrown must be a Throwable (or a valid subclass) – Though, typically we throw Exceptions (or subclasses) Object Throwable Error Error Error … Exception Error Error … RuntimeException Error Error … Exceptions in Java • Here’s a Java port of that second example – We’re using the built-in Exception class… static int factorial(int n) { // check for exceptional case if(n < 0) { throw new Exception("number must be positive"); } // computation for normal case int result = 1; for(int i = n; i > 0; i--) { result *= i; } return result; } Exceptions in Java • Here is the invoking function in Java, with the try/catch block added… public static void main(String[] args) { int num = -4; try { System.out.println("factorial(" + num + "): " + factorial(num)); } catch(Exception e) { System.err.println(e.getMessage()); } } Exceptions in Java • But, if we try to compile this, we get the following error… $ javac.exe Factorial.java Factorial.java:19: unreported exception java.lang.Exception; must be caught or declared to be thrown throw new Exception("number must be positive"); ^ 1 error • Why? Java Exception Hierarchy • Java breaks up Exceptions into 2 categories – Unchecked: you do not need to explicitly handle these exceptions – Checked: you must handle these in your code, failure to do so is a compiler error Object Throwable Unchecked Error Error Error … Exception Error Error … Checked RuntimeException Error Error … Handling Checked Exceptions • We have one of 2 options… – Handle the exception locally (wrap code in a try/catch block) – Propagate the exception by adding a throws declaration to the method signature Exceptions in Java • The modified factorial function modified to declare an thrown exception… static int factorial(int n) throws Exception { // check for exceptional case if(n < 0) { throw new Exception("number must be positive"); } // computation for normal case int result = 1; for(int i = n; i > 0; i--) { result *= i; } return result; } Exceptions in Java • Other notes about exceptions in Java… – e.printStackTrace() will print out the full stack trace as to where an exception originated – e.getMessage() will give you a detailed message string as to why the exception occurred – Try/catch blocks may also have a finally section with code in it • Always executed even if a return or throw is encountered Console I/O in C++ • Simple C++ class that reads/writes to the console #include <iostream> using namespace std; int main() { int n; string s; cout << "What do you want to buy: "; cin >> s; cout << "How many: "; cin >> n; cout << "You want " << n << " " << s << endl; return 0; } Console Input/Output in Java • Already looked at System.out for print() and println(), though there are many more such as – printf() – C style output (added in Java 5) – write() – byte based output • System.err provides the same methods as System.out does, goes to stderr • System.in interface is our standard input stream – System.in is an InputStream class and is pretty low level (read bytes) – Typically another class is used to read from System.in Console Input in Java • Scanner class was added in JSE 5 to simplify input… – Has a constructor which takes an InputStream class • Scanner(System.in) – Methods are available to read common data types… • • • • nextBoolean() nextFloat(), nextDouble() nextShort(), nextInt(), nextLong() next() - reads next String – Corresponding methods to check and see if another value is in stream… • i.e. hasNextInt() • http://java.sun.com/j2se/1.5.0/docs/api/java/util/Scanner.html Console I/O in Java • Java port of our C++ example… import java.util.Scanner; public class ConsoleIO { public static void main(String[] args) { Scanner console = new Scanner(System.in); System.out.print("What do you want to buy: "); String s = console.next(); System.out.print("How many: "); int n = console.nextInt(); System.out.println("You want " + n + " " + s); } } File Input in C++ • Example reading integers from a file… #include <fstream> #include <iostream> using namespace std; int main() { int num; fstream in("file.txt", ios::in); while(in >> num) { cout << "read " << num << endl; } in.close(); return 0; } File Input in Java • Java port of C++ example… import java.io.File; import java.util.Scanner; public class FileIO { public static void main(String[] args) { try { Scanner in = new Scanner(new File("file.txt")); while(in.hasNextInt()) { System.out.println("read " + in.nextInt()); } in.close(); } catch (Exception e) { e.printStackTrace(); } } } File Output in C++ • Output to a file in C++… #include <fstream> #include <iostream> using namespace std; int main() { fstream out("file.txt", ios::out); for(int i = 0; i < 10; i++) { out << i << endl; } out.close(); return 0; } File Output in Java • Java port of C++ example (PrintStream is same class as System.out, so same methods available)… import java.io.PrintStream; public class FileIO { public static void main(String[] args) { try { PrintStream out = new PrintStream("file.txt"); for(int i = 0; i < 10; i++) { out.println(i); } out.close(); } catch (Exception e) { e.printStackTrace(); } } } Exercises 1. Write an Direction enum for the 4 cardinal directions (North, South, East & West). Then write (in another class) a walk method which takes a Direction enum as an argument 2. Write a class which reads numbers from one file (the 1st command line arg) and writes out each number squared to a second file (the 2nd command line arg) Break C++ Templates • C++ allows us to define generic (template) types which can hold whatever type we specify • Frequently people include the C file at the end of the header file • Gotchas… – Compilation – Mixing templated and non-templated code – Spaces with respect to nested templates C++ Templates • Example node header file… #ifndef _NODE_H_ #define _NODE_H_ template <class T> class Node { private: T m_data; public: Node(T data); T GetData() const; }; #include "node.C" #endif C++ Templates • Corresponding implementation in C++ #ifndef _NODE_C_ #define _NODE_C_ #include "Node.H" template <class T> Node<T>::Node(T data) { this->m_data = data; } template <class T> T Node<T>::GetData() const { return this->m_data; } #endif C++ Templates • Example usage… #include <iostream> #include <string> #include "node.H" using namespace std; int main() { Node<string> n("hamburger"); cout << n.GetData() << endl; return 0; } Java Generics • Java introduced Generics in Java 5 which are similar to C++’s templates – Syntax is a bit less burdensome • Parts of the Java SE API are capable of using generics – Prior to Java 5, all of these things stored Object’s and were thus capable of storing any object what-so-ever (as it had to be a subclass of Object) Java Generics • Port of templated Node class to Java… public class Node<T> { private T data; Node(T data) { this.data = data; } T getData() { return this.data; } } Java Generics • Example driver… public class NodeTest { public static void main(String[] args) { Node<String> n = new Node<String>("hamburger"); System.out.println(n.getData()); } } Generics Gotchas • Cannot use primitive types as the generic type… – In C++ this is completely valid… Node<int> n(516); – In Java, this is not… Node<int> n = new Node<int>(516); – We can still store an int, char, float or boolean, but we need to do something slightly different Wrapper Classes • For each of the primitive types, Java provides a “wrapper class” • Wrapper class is an object which stores the given primitive type… – – – – Integer – stores an int primitive Boolean – stores a boolean primitive Float – stores a float primitive Etc… • We can declare our generic type to be of the wrapper class type Wrapper Classes & Generics • Example using the Integer wrapper class to store ints • In Java 5, primitives are automatically converted to and from the corresponding wrapper type as needed – This is known as auto boxing/un-boxing public class NodeTest { public static void main(String[] args) { Node<Integer> n = new Node<Integer>(516); System.out.println(n.getData()); } } Generics Gotchas • In C++, you can create an array of a templates type… template <class T> void Node<T>::SomeTemplatedFunction() { T array[10]; } • Java does not permit this, you end up with a compiler error… void SomeTemplatedFunction() { T array[10]; } Generics Bounding • Allow a method to take anything that subclasses T void foo(Collection<? extends T> items) { /* ... */ } • Allow only classes that implement the Comparable interface… void foo(Collection<? extends Comparable> items) { /* ... */ } C++ STL • The C++ STL provides numerous built-in data types that are used by programmers • Some of the more commonly used ones are… – vector – iterators – deque – list – map Java SE API • One thing you will notice about Java is that the Java SE API is huge – Java SE 6 has Nearly 3800 classes, interfaces & enums in the built-in API • Bookmark the javadocs, they are your friend… – http://java.sun.com/javase/6/docs/api/ Java Collections Framework • Java has a robust collections (containers) framework – With Java 5, these have been generified to support arbitrary types with strong typing – There are interfaces provided for many ADTs • List, Set, Map, etc… – There are also multiple concrete implementations of many of the data structures, each providing their own advantages… • ArrayList, LinkedList, Stack, Vector, etc… – Typically you instantiate a concrete implementation, but maintain a handle on it based on its interface • Interface<type> = ImplementationOfInterface<type>(); C++ Vector • Sample C++ Vector usage… #include <vector> #include <iostream> using namespace std; int main() { vector<int> v; v.push_back(1); v.push_back(20); v.push_back(2009); for(int i = 0, n = v.size(); i < n; i++) { cout << v[i] << endl; } for(vector<int>::iterator itr = v.begin(); itr != v.end(); itr++) { cout << *itr << endl; } return 0; } Java Vector • Port of the C++ vector example… import java.util.Vector; public class VectorTest { public static void main(String[] args) { Vector<Integer> v = new Vector<Integer>(); v.add(1); v.add(20); v.add(2009); for(int i = 0, n = v.size(); i < n; i++) { System.out.println(v.get(i)); } for(int tmp : v) { System.out.println(tmp); } } } C++ List • Sample C++ Vector usage… #include <iostream> #include <list> using namespace std; int main() { list<int> l; l.push_front(1); l.push_front(2); l.push_back(3); l.push_back(4); list<int>::iterator itr; for (itr = l.begin(); itr != l.end(); itr++) { cout << *itr << endl; } cout << l.front() << endl; l.pop_front(); cout << l.front() << endl; } Java List • Port of the C++ list example… import java.util.LinkedList; import java.util.List; public class ListTest { public static void main(String[] args) { List<Integer> l = new LinkedList<Integer>(); l.add(1); l.add(0, 2); l.add(l.size(), 3); l.add(l.size(), 4); for(int i : l) { System.out.println(i); } System.out.println(l.get(0)); l.remove(0); System.out.println(l.get(0)); } } C++ Map • Sample C++ map usage… #include <iostream> #include <map> #include <string> using namespace std; int main() { map<int, string> courses; courses[201] = "Computer Science I"; courses[202] = "Computer Science II"; courses[341] = "Data Structures"; map<int, string>::iterator itr; for (itr = courses.begin(); itr != courses.end(); itr++) { cout << itr->first << ": " << itr->second << endl; } return 0; } Java Map • Port of the C++ map example… import java.util.Iterator; import java.util.Map; import java.util.TreeMap; public class MapTest { public static void main(String[] args) { Map<Integer, String> courses = new TreeMap<Integer, String>(); courses.put(201, "Computer Science I"); courses.put(202, "Computer Science II"); courses.put(341, "Data Structures"); Iterator<Integer> itr; for (itr = courses.keySet().iterator(); itr.hasNext();) { int num = itr.next(); System.out.println(num + ": " + courses.get(num)); } } } C++ Deque • Sample C++ deque usage… #include <deque> #include <iostream> using namespace std; int main() { deque<int> d; d.push_front(1); d.push_front(2); d.push_back(3); d.push_back(4); deque<int>::iterator itr; for (itr = d.begin(); itr != d.end(); itr++) { cout << *itr << endl; } cout << d.front() << endl; d.pop_front(); cout << d.front() << endl; return 0; } Java Deque • Port of the C++ deque example… import java.util.ArrayDeque; import java.util.Deque; public class DequeTest { public static void main(String[] args) { Deque<Integer> d = new ArrayDeque<Integer>(); d.addFirst(1); d.addFirst(2); d.addLast(3); d.addLast(4); for (int i : d) { System.out.println(i); } System.out.println(d.getFirst()); d.removeFirst(); System.out.println(d.getFirst()); } } Exercises 1. Create, compile and run a program which puts several Person objects into a Vector and iterates over them and prints each out • The members in a Person are up to you, but there should be at least one, and toString should overridden