Basicjava03 Code Organization Slides
Basicjava03 Code Organization Slides
Kozsik Tamás
...
...
TestTime.java
Time time = new Time(6,30);
time.setHour(30);
Good solutions
• IllegalArgumentException: at module boundaries
• assert: inside a module
• Doc comment
Bad solutions
• Silently not perform the requested operation
• Do not check correct behaviour, let the program go wrong
Exceptions
Exceptions
Exceptions
import java.io.IOException;
public class TestTime {
public Time readTime(String fname) throws IOException {
... new java.io.FileReader(fname) ...
}
Exceptions
import java.io.IOException;
public class TestTime {
public Time readTime(String fname) throws IOException {
... new java.io.FileReader(fname) ...
}
Exception handling
Exception handling
Exception handling
Multiple catch-clauses
public static Time parse(String str) {
String errorMessage;
try { String[] parts = str.split(":");
int hour = Integer.parseInt(parts[0]);
int minute = Integer.parseInt(parts[1]);
return new Time(hour,minute);
} catch (NullPointerException e) {
errorMessage = "Null parameter is not allowed!";
} catch (ArrayIndexOutOfBoundsException e) {
errorMessage = "String must contain \":\"!";
} catch (NumberFormatException e) {
errorMessage = "String must contain two numbers!";
}
throw new IllegalArgumentException(errorMessage);
}
Kozsik Tamás Programming languages Java 11 / 80
Exception ~ handling Doc Paradigm Param final Aliasing
Exception handling
finally
finally
finally
finally
Nesting try-statements
public static Time readTimeOrUseDefault(String fn) {
try {
var in = new BufferedReader(new FileReader(fn));
try {
String line = in.readLine();
return parse(line);
} finally {
in.close();
}
} catch (IOException | IllegalArgumentException e) {
System.err.println(e);
System.err.println("Using default value!");
return new Time(0,0);
}
}
Kozsik Tamás Programming languages Java 16 / 80
Exception ~ handling Doc Paradigm Param final Aliasing
Try-with-resources
Try-with-resources
try-finally try-with-resources
try (
BufferedReader in = ...
BufferedReader in = ...;
) {
try {
String line = in.readLine();
String line = in.readLine();
return parse(line);
return parse(line);
}
} finally {
in.close();
}
Try-with-resources
Documentation comment
Documentation comment
Documentation comment
/**
Blindly sets the hour property to the given value.
Use it with care: only pass {@code hour} satisfying
{@code 0 <= hour && hour <= 23}.
*/
public void setHour(int hour) {
this.hour = hour;
}
javadoc
javadoc Time.java
javadoc
javadoc Time.java
Details
Details
javadoc Time.java
Details
Syntax highlighting
package numbers;
public class Rational {
private int numerator, denominator;
/* class invariant: denominator > 0 */
Getter-setter
package numbers;
public class Rational {
private int numerator, denominator;
...
}
import numbers.Rational;
public class Main {
public static void main(String[] args) {
Rational p = new Rational(1,3);
Rational q = new Rational(1,2);
p.multiplyWith(q);
println(p); // 1/6
println(q); // 1/2
}
private static void println(Rational r) {
System.out.println(r.getNumerator()+"/"+r.getDenominator());
}
}
Arithmetics
package numbers;
public class Rational {
private int numerator, denominator;
public Rational(int numerator, int denominator) { ... }
public int getNumerator() { return numerator; }
public int getDenominator() { return denominator; }
public void setNumerator(int numerator) { ... }
public void setDenominator(int denominator) { ... }
Doc comment
package numbers;
public class Rational {
...
/**
* Set {@code this} to {@code this} * {@code that}.
* @param that Non-null reference to a rational number,
* it will not be changed in the method.
* @throws NullPointerException When {@code that} is null.
*/
public void multiplyWith(Rational that) {
this.numerator *= that.numerator;
this.denominator *= that.denominator;
}
...
}
Kozsik Tamás Programming languages Java 31 / 80
Exception ~ handling Doc Paradigm Param final Aliasing
Sequencing operations
package numbers;
public class Rational {
...
public Rational multiplyWith(Rational that) {
this.numerator *= that.numerator;
this.denominator *= that.denominator;
return this;
}
...
}
Procedural/modular style
Procedural/modular style
A different approach
package numbers;
public class Rational {
...
public void multiplyWith(Rational that) { ... }
public Rational times(Rational that) { ... }
}
Implementations
package numbers;
public class Rational {
private int numerator;
private int denominator;
public Rational(int numerator, int denominator) { ... }
...
public Rational times(Rational that) {
return new Rational(this.numerator * that.numerator,
this.denominator * that.denominator);
}
public void multiplyWith(Rational that) {
this.numerator *= that.numerator;
this.denominator *= that.denominator;
}
}
Implementations
package numbers;
public class Rational {
private int numerator;
private int denominator;
public Rational(int numerator, int denominator) { ... }
...
public Rational times(Rational that) {
return new Rational(this.numerator * that.numerator,
this.denominator * that.denominator);
}
public Rational multiplyWith(Rational that) {
this.numerator *= that.numerator;
this.denominator *= that.denominator;
return this;
}
}
package numbers;
public class Rational {
private final int numerator, denominator;
public Rational(int numerator, int denominator) {
if (denominator <= 0) throw new IllegalArgumentException();
this.numerator = numerator;
this.denominator = denominator;
}
public int getNumerator() { return numerator; }
public int getDenominator() { return denominator; }
public Rational times(Rational that) { ... }
public Rational plus(Rational that) { ... }
...
}
Similar methods
Similar methods
Similar methods
Similar methods
Overloading
Overloading
Overloading
Overloading
Overloading
Overloading
Overloading
Overloading
Overloading
Overloading
Overloading
Is this correct?
public class Rational {
...
Overloading
Meaningful overloading
public class Rational {
...
public void set(int numerator, int denominator) {
if (denominator <= 0) throw new IllegalArgumentException();
this.numerator = numerator;
this.denominator = denominator;
}
Overloading
Overloading
Overloading
public Rational() {
this(0);
}
...
}
Kozsik Tamás Programming languages Java 50 / 80
Exception ~ handling Doc Paradigm Param final Aliasing
Overloading
Parameter passing
• Textual substitution
• Call-by-value
• Call-by-value-result
• Call-by-result
• Call-by-reference
• Call-by-sharing
• Call-by-name
• Call-by-need
Parameter passing
Call-by-sharing
parameters of reference types (the reference is passed by value)
public static void multiplyLeftWithRight(Rational left,
Rational right) {
left.numerator *= right.numerator;
left.denominator *= right.denominator;
}
Parameter passing
Call-by-value
Parameter passing
Call-by-sharing
Parameter passing
Parameter passing
final variables
Global constants
final variables
Final field
final variables
final variables
Erroneous
static java.math.BigInteger factorial(final int n) {
assert n > 0;
java.math.BigInteger result = java.math.BigInteger.ONE;
while (n > 1) {
result = result.multiply(java.math.BigInteger.valueOf(n));
--n;
}
return result;
}
final variables
Correct
static java.math.BigInteger factorial(final int n) {
assert n > 0;
java.math.BigInteger result = java.math.BigInteger.ONE;
for (int i=n; i>1; --i) {
result = result.multiply(java.math.BigInteger.valueOf(i));
}
return result;
}
Immutability
Immutability
Immutability
Immutability
Side note
int[] s = {1,2,3};
s = {1,2,3,4}; // compilation error
s = new int[]{1,2,3,4};
final reference
final reference
final reference
final reference
final reference
final reference
final reference
final reference
Performance?
Aliasing
Aliasing
Aliasing
Aliasing
Aliasing
Defensive copy
Defensive copy
Defensive copy
Arrays
Aliasing in an array
Arrays
/**
...
PRE: rats != null
...
*/
public static void increaseAllByOne(Rational[] rats) {
for (Rational r: rats) {
r.setNumerator(r.getNumerator() + r.getDenominator());
}
}
Arrays
Doc comment
/**
...
PRE: rats != null and (i!=j => rats[ i] != rats[ j])
...
*/
public static void increaseAllByOne(Rational[] rats) {
for (Rational r: rats) {
r.setNumerator(r.getNumerator() + r.getDenominator());
}
}
Arrays
Arrays of arrays
Arrays
Rational[][] matrix =
{ {new Rational(1,2), new Rational(1,2)},
{new Rational(1,2), new Rational(1,2)},
{new Rational(1,2), new Rational(1,2)} };