General Stuff
// Point.java
public class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}// Shape.java
abstract class Shape implements GetAreable, Comparable { // comparable not actually implemented, just an example
private int numAxesOfSymmetry;
public boolean isSymmetric() {
return numAxesOfSymmetry > 0;
}
}// Circle.java
public class Circle extends Shape {
Point centre;
int radius;
public Circle(Point centre, int radius) {
this.centre = centre;
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * Math.pow(r, 2);
}
@Override
public boolean equals(Object x) {
return false;
}
public boolean equals(Circle c) {
return this.centre.equals(c.centre) && this.radius == c.radius;
}
}// ColouredCircle.java
public class ColouredCircle extends Circle {
String colour;
public ColouredCircle(Point centre, int radius, String colour) {
super(centre, radius);
this.colour = colour;
}
@Override
public boolean equals(ColouredCircle c) {
return super.equals(c) && this.colour == c.colour;
}
}// GetAreable.java
public interface GetAreable {
double getArea();
}// Main.java
public class Main {
public static void main(String[] args) {
Point origin = new Point(0,0);
Shape[] shapes = {
new Circle(origin, 1),
new ColouredCircle(origin, 1, "green") }
// or Shape[] shapes = new Shape[2] for empty array
// shapes.length is the array length
for (Shape shape : shapes) {
System.out.println(shape.getArea());
}
}
}Exceptions
// MyFileNotFoundException.java
// This is a checked exception, which means we have to handle it with a try catch, or declare it with a throws statement. It is checked at compile time.
// This is used when the exception is caused by something out of our control e.g. a file not existing, web request fail etc.
class MyFileNotFoundException extends Exception {
public MyFileNotFoundException(String message) {
super(message);
}
@Override
public String getMessage() {
return "File not found! Message: " + super.getMessage();
}
}// ArrayIndexException.java
// This is an unchecked exception, which means we do not need to handle it in the code.
// This is used for programmer error e.g. null pointer exception, array index out of bounds
class ArrayIndexException extends RuntimeException {
}class Example {
public String readFile(String path) throws MyFileNotFoundException {
// ...
throw new MyFileNotFoundException("file " + path + " not found!");
}
public String readFiles(String[] paths) {
String result = "";
for (String path : paths) {
try {
result += this.readFile(path)
} catch (MyFileNotFoundException e) {
System.out.println(e.getMessage());
} finally {
// this code is always run
System.out.println("done with a file!");
}
}
}
}In CS2030S, we should always use a finally block
Generic Types
Generic Class
// Pair.java
public class Pair<S, T> {
// convention: type parameters are single capital letters
private S first;
private T second;
public Pair(S first, T second) {
this.first = first;
this.second = second;
}
public S getFirst() {
return this.first;
}
public T getSecond() {
return this.second;
}
}
// note: generic types need to be reference types, not primatives
// does not work, int is not a reference type:
Pair<int, String> a = new Pair<int, String>(123, "Hello");
// works:
Pair<Integer, String> a = new Pair<Integer, String>(123, "Hello");
// syntax to use the type parameters of the variable:
Pair<Integer, String> a = new Pair<>(123, "Hello"); // <> diamond operator is equivalent to above
// Generic types can be bound,
public class Pair<S extends Abc, T> {// ... }
// Abc can be a class or interface. This just means that S should be a subtype of Abc
// Multiple bounds
public class Pair<S extends Abc & Def, T> {// ... }Generic Method
// Contains.java
public class Contains {
public static <T> boolean contains(T[] items, T target) {
for (T item : items) {
if (item.equals(target)) {
return true;
}
}
return false;
}
}
// application
Integer[] ints = new Integer[] {1,2,3};
Contains.<Integer>contains(ints, 2);Generics cannot be used with arrays, due to type erasure
new Pair<String, Integer>[2]; // error
class Abc<S, T> {
private S[] arr; // ok
// ...
new Pair<S, T>[2]; // error
this.arr = new S[2]; // error
this.arr = (S[]) new Object[2]; // ok, but produces warning
// to suppress this warning:
@SuppressWarnings("unchecked") // be careful of how items can be added to the array
S[] a = (S[]) new Object[2];
this.arr = a;
}Wildcards
class Shape {}
class Circle extends Shape {}
class Container<T> {
private T item;
public Container(T item) {
this.item = item;
}
public T get() {
return item;
}
public void set(T item) {
this.item = item;
}
// upper bound wildcard
// we want to allow copying from a container that contains anything that is a subtype of T
public void copyFrom(Container<? extends T> c) {
this.item = c.get();
}
// lower bound wildcard
// we want to allow copying to a container that contains anything that is a supertype of T
public void copyTo(Container<? super T> c) {
c.set(this.item);
}
}
// demo
Shape s = new Shape();
Circle c = new Circle();
Container<Shape> sc = new Container<>(s);
Container<Circle> cc = new Container<>(c);
sc.copyFrom(cc); // ok
cc.copyFrom(sc); // error
cc.copyTo(sc); // ok
sc.copyTo(cc); // error@SuppressWarnings("unchecked")
Queue<Passenger>[] q = (Queue<Passenger>[]) new Queue<?>[nStops];
this.queues = q; // Queue<Passenger> <: Queue<?>