Java for C++ Programmers Second Night

advertisement
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
Download