• Objects and Classes

    The concept of classes: Blueprints for objects.

    Example: Rectangles

    UML diagram visualization.

Instances of a Class
General class structure

In object oriented languages classes:

  • are blueprints for objects.

  • contain attributes and methods.

  • allow for implementation hiding.

  • allow for tailored access to methods and attributes.

Rectangle objects
public class Rectangle {
  int width;
  int height;

  // solid or dashed:
  boolean hasSolidBorder;
}
A class describing rectangles
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
Generated diagrams
Generated diagrams
  • Objects and Classes
    • ➟ Working with objects

      Classes and creation of related instances.

      The «new» operator.

      Assignment of attribute values. Working with «null».

Rectangle dashedRectangle = new Rectangle();

Rectangle solidRectangle = new Rectangle();

...
new class-name ([argument 1[, argument 2] ...] )
Wording examples:
  • Create an instance of class Rectangle.

  • Create a Rectangle object.

  • Create a Rectangle.

Rectangle dashedRectangle = new Rectangle();

dashedRectangle.width = 28;
dashedRectangle.height = 10;
dashedRectangle.hasSolidBorder = false;

Syntax accessing object attributes:

variable.attributeName = value;
Instance memory representation
Rectangle r = new Rectangle();// Creating an object

r.width = 28; // o.K.

r = null;// removing reference to object

r.width = 28; // Runtime error: NullPointerException (NPE)
Exception in thread "main" java.lang.NullPointerException
  at de.hdm_stuttgart.mi.classdemo.App.main(App.java:17)
Rectangle r;

... // possible object assignment to variable r.

if (null == r) {
  System.out.println("No rectangle on offer");
} else {
  System.out.println("Width:" + r.width);
}
  • Objects and Classes
    • ➟ Packages

      Significance for larger projects.

      Fully qualified vs. «import».

      java.lang and other exceptions.

  • Grouping of related classes (e.g. subsystems).

  • Structuring big systems.

  • Provide access restrictions using:

    public, private and protected modifier

  • Resolving class name clashes. Example:

    java.lang.String vs. my.personal.String

  • Package names below java. are reserved.

  • Package names should not start with javax. either.

  • Package names must not contain operators:

    mi.hdm-stuttgart.de --> de.hdm_stuttgart.mi.

  • Packages should start with reversed DNS avoiding clashes.

Fully qualified class name:
java.util.Scanner  scanner =          // Clumsy and
   new java.util.Scanner (System.in); // redundant
Using import:
import java.util.Scanner; 

public class Q {

  public static void main(String[] args) {
     Scanner  scanner = new Scanner (System.in);
       ...
  }
}
Bad Good
import java.util.*;

public class Q {
  public static void
        main(String[] args) {
    Scanner s = 
      new Scanner(System.in);
    Date today = new Date();
  }
}
import java.util.Scanner;
import java.util.Date;

public class Q {
  public static void
         main(String[] args) {
    Scanner s =
       new Scanner(System.in);
    Date today = new Date();
  }
}
import java.lang.String;   // Optional
import java.util.Scanner;  // Required
public class Q {

  public static void main(String[] args) {
    String message = "Hello!";
    Scanner  s = new Scanner(System.in);
  }
}
Class, package and file system
Source hierarchy view
package my.first.javapackage;
        ❷ ❸     ❹
public class Print { 
              ❺
  ...


}
  • Objects and Classes
    • ➟ Object methods

      Object behaviour, state transitions, derived values.

      Selected examples both of state-changing and state-conserving methods.

      Rectangle sample methods.

Change an object's state.

Example: Scale a rectangle.

Get dependent values

Example: Calculate a rectangle's perimeter.

Combined

Scale a rectangle and calculate its new perimeter.

layered SVG image
layered SVG image
layered SVG image
public class Rectangle {
    int width, height;
    boolean hasSolidBorder;

    public void scale (int factor) {
        width *= factor;
        height *= factor;
    }
}
Scaling method implementation
void  scale (int factor ) {
...}

No value is being returned to caller.

A single value of type int is being provided as method argument.

Rectangle r = new Rectangle();
r.width = 33;
r.height = 22;

r.scale(2);

System.out.println("width=" + r.width);
System.out.println("height=" + r.height);
width=66
height=44
public  void  scale (int factor ) { 
   width *= factor; 
   height *= factor;
}
[access modifier]  return_type  methodName  ([arguments] ) {
   [statement(s)] 
}
layered SVG image
layered SVG image
layered SVG image
public class Rectangle {
    int width, height;
    boolean hasSolidBorder;

    public void scale (int factor) { ... }

    public int getPerimeter() {
        return 2 * (width + height);
    }
}
getPerimeter() method
      implementation
Rectangle r = new Rectangle();

r.width = 33;
r.height = 22;

System.out.println("Perimeter=" + r.getPerimeter());
Perimeter=110
  1. Compile time error
  2. Static code analysis
  • Objects and Classes
    • ➟ Object methods
      • ➟ Encapsulation and access control

        Justifying access restrictions.

        public, protected «package local» and private.

        Best practices.

public class Time {
  private long  secondsSince_2000_01_01;

  public int getSecond() { 
    return
    (int) secondsSince_2000_01_01 % (60);
  }
  public int getMinute() {
    return (int)
      (secondsSince_2000_01_01 / 60) % 60;
  }
    ...
}
public class Time {
  private int second, minute,
         hour,day, month, year;

  public int getSecond() { 
        return second;
  }
  public int getMinute() { 
        return minute;
  }
    ...
}

No access to private field of alien class Time:

public class Q {
  public static void main(String[] args) {

      Time t = new Time();

      // Error: 'secondsSince_2000_01_01' has private access in 'Time'
      t.secondsSince_2000_01_01 = 33445354L;
  }
}
Access Level Other package Child class Same package Same class
public yes yes yes yes
protected no yes yes yes
Default no no yes yes
private no no no yes
  • Use the most restrictive access level that makes sense for a particular member.

  • Use private unless you have a good reason not to.

  • Avoid public fields except for constants. Public fields tend linking to a particular implementation and limit your flexibility in changing your code.

  1. Understanding access control
  2. Explaining times
  • Objects and Classes
    • ➟ Object methods
      • ➟ Getter and setter methods
package hour_second.direct;

public class Time {
    public int hour, minute;
}
package hour_second;
import hour_second.direct.Time;

public class DirectAccess {
    Time time = new Time();
    void init() {
        time.hour = 17;
        time.minute = 45;
    }
}
package hour_second.setter;

public class Time {
    private int hour, minute;
    public void setTime(int h, int m) {
        minute = m;
        hour = h;
    }
}
package hour_second;
import hour_second.setter.Time;
public class SetterAccess {
    Time time = new Time();
    void init() { time.setTime(17, 45);}
}
  • Allow for change of implementation.

  • Allow for non-business logic concerns. Examples:

    • Logging

    • Adding persistence

package only_minute.direct;
public class Time {
  // Minutes since 00:00
  public int minute;
}
package only_minute;
import only_minute.direct.Time;
public class DirectAccess {
  Time time = new Time();
  void init() {
    time.minute = 1065;// 17:45
  }
}
package only_minute.setter;
public class Time {
  private int minute;
  public void setTime(int h, int m) {
    minute = m + 60 * h;
  }
}
package only_minute;
import only_minute.setter.Time;
public class SetterAccess {
    Time time = new Time();
    void init() { time.setTime(0, 0);}
}
  • Objects and Classes
    • ➟ Object methods
      • ➟ Signatures

        Type signatures.

        Method signatures: Prerequisite understanding method overloading.

boolean  startsWith​(String prefix, int toffset)  

Return type boolean

Arguments among with their respective types and order:

  1. Type String

  2. Type int

Method Return type Argument type list
void print() void (void)
int add (int a, int b) int (int, int)
int max (int a, int b) int (int, int)
void print (int a, float b) void (int, float)
void display (float a, int b) void (float, int)
boolean startsWith(String prefix, int toffset)  

Method name startsWith.

Number of arguments among with their respective types and order.

Method Method name Method signature
void print() print (void)
int add (int a, int b) add (int, int)
int max (int a, int b) max (int, int)
void print (int a, float b) print (int, float)
void display(float a, int b) display (float, int)
Method signature variants
  • Objects and Classes
    • ➟ Object methods
      • ➟ Method overloading

        Same name, different argument types.

        «C» programming language comparison.

        Common examples.

public class Print {
  public void print() {             // (void)
    System.out.println("No argument");
  }
  public void print(int i) {        // (int)
    System.out.println("int value " + i);
  }
  public void print(double d) {     // (double)
    System.out.println("double value " + d);
  }
  public void print(int i, int j) { // (int, int)
      System.out.println("Two int values "+
         i + " and " + j);
  }
}
Print p = new Print();
p.print();
p.print(33);
p.print(4.333);
p.print(-1, 7);
No argument
int value 33
double value 4.333
Two int values -1 and 7
  • Static polymorphism.

  • Compile time binding.

  • Early binding.

void print() {
  printf("No argument\n");
}

void print(int i) {              /* Error: redefinition of ‘print’ */
  printf("int value %d\n", i);
}

void main(void) {
  print();
  print(33);
}
public class Person {
  String getDetails() { return "dummy";}
  int getDetails() { return 1;} // Error: 'getDetails()' is already
}                                // defined in 'Person'
Return type Method signature
Method name Argument type list
String getDetails (void)
int getDetails (void)

Only method signature support in Java ignoring return type.

In Java method signatures allow for uniquely addressing a method within a given class e.g.:

The method named print having an int argument followed by a double:

print(int, double)
Method signatures rationale
Will a match be found?
  • Objects and Classes
    • ➟ Object methods
      • ➟ Constructors

        Combined instance creation and initialization.

        Constructors are methods, but ...

        Constructor overloading and a class' default constructor.

int a;
a = 33;
Rectangle r = new Rectangle();

r.width = 28;
r.height = 10;
r.hasSolidBorder = false;

Combining statements desired:

int a = 33; // works!
Rectangle r = new Rectangle(28, 10, false);//how ???
public class Rectangle {
    int width, height;
    boolean hasSolidBorder;
         ...
    public  Rectangle  (int width, int height, boolean hasSolidBorder){
        this.width = width;
        this.height = height;
        this.hasSolidBorder = hasSolidBorder;
    }
}
[access modifier] constructorName (listOfArguments) {
    [constructor body]
}
Empty argument list

Default constructor e.g. obj = new MyClass().

Non-empty argument list

Non-default constructor e.g. :

obj = new String("xyz");
  • Can only be executed on object creation.

  • Are being called prior to any non-constructor method.

  • Only one of potentially multiple constructors will be executed exactly one time.

    However nesting is possible.

public class Rectangle {
    int width, height;

    public Rectangle() {
        width = height = 1;
    }
    public Rectangle(int width, int height){
        this.width = width;
        this.height = height;
    }
    public Rectangle(int widthAndHeight) {
        width = height = widthAndHeight;
    }
}
public class Rectangle {
  int width, height;

  public Rectangle(int width,
                int height){
    this.width = width;
    this.height = height;
  }
  public Rectangle() {
    width = height = 1;
  }
  public Rectangle(
     int widthAndHeight) {
    width = height =
          widthAndHeight;
  }
}
   public class Rectangle {
     int width, height;

 ┏━▶ public Rectangle(int width,
                     int height){
      this.width = width;
      this.height = height;
    } 
    public Rectangle() { 
 ┣━◀━━ this(1, 1);           
    }
    public Rectangle(
      int widthAndHeight) {
 ┗━◀━━ this(widthAndHeight,   
            widthAndHeight); 
     }
   }
Rectangle standard = new Rectangle(); // 1 x 1
Rectangle square = new Rectangle(2); // 2 x 2
Rectangle individual = new Rectangle(2, 7); // 2 x 7
Instances by overloaded constructors
Equivalent: Rectangle r = new Rectangle();
public class Rectangle {
    int width, height;
    boolean hasSolidBorder;

    // Default constructor, empty body.
    public Rectangle ( ){}
}
public class Rectangle {
    int width, height;
    boolean hasSolidBorder;

  // No constructor at all
}
public class Rectangle {
  int width, height;
  boolean hasSolidBorder;

  // Non-default constructor
  public Rectangle(int width,
                  int height,
    boolean hasSolidBorder){
      this.width = width;
      this.height = height;
      this.hasSolidBorder =
                hasSolidBorder;
  }

 // No defined default constructor.
}
// o.K.: Using non-default
// constructor.

Rectangle r = 
   new Rectangle(3, 6, false);
// Wrong: Default constructor
// undefined, but non-default
// constructor present.

Rectangle r = new Rectangle();
  1. Modeling geometry objects: Rectangles
  2. Modeling circles
  3. Adding translations and SVG export.
  4. Extending the employee example.
  5. Refining access to an employee's attributes
  6. File system representation
  7. Constructors variable names and this.
  8. Your personal String class
  • Objects and Classes
    • ➟ Object methods
      • ➟ Scopes

        Class, method and block scopes.

        Documentation, «good» variable names and the this keyword.

layered SVG image
layered SVG image
layered SVG image
/** Representing circles.
 */
public class Circle {
  private double radius;

  /** Creating a circle.
   *  @param r representing the circle's radius
   */
  public Circle(double r) {
    radius = r;
  }
  public double getDiameter() {
    return 2 * radius;
  }
}
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
/** Representing circles.
 */
public class Circle {
  private double radius;

  /** Creating a circle.
   *  @param radius Circle's size
   */
  public Circle(double radius) {
    radius = radius; // Warning: Variable 'radius' is assigned to itself.
  }
  public double getDiameter() {
    return 2 * radius;
  }
}
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
Turning seconds into weeks, part 2
  • Objects and Classes
    • ➟ Class members and methods

      Motivating class attributes and methods.

      Example: A club and its affiliated members.

      Syntax of static and employment considerations

  • Each club member has got a name.

  • Each member has got an ascending unique membership number.

  • The overall club's member count needs to be accounted for.

Solution:

  • Class level: Advance club's member count by each new member.

  • Instance level: New instances receive current member count.

public class ClubMember {

  final private String name;

  public ClubMember(final String name) {
    this.name = name;
  }
  public String getDetails() {
    return "Member " + name;
  }
}
final ClubMember
   john = new ClubMember("John"),
  karen = new ClubMember("Karen");

System.out.println(john.getDetails());
System.out.println(karen.getDetails());
Member John
Member Karen
public class ClubMember {

  static  private int memberCount = 0;

  final private int memberNumber; 
  final private String name;

  public ClubMember(final String name) {
    this.name = name;
    memberNumber = ++memberCount; 
  }
  public String getDetails() {
    return "Member " + name + ", member number " + memberNumber ;
  }
}
final ClubMember
   john = new ClubMember("John"),
  karen = new ClubMember("Karen");

System.out.println(john.getDetails());
System.out.println(karen.getDetails());
Member John, member number 1
Member Karen, member number 2
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
public class ClubMember {

  static private int memberCount = 0;
  ...
  public ClubMember(final String name) {
    this.name = name;
    memberNumber = ++memberCount;
  }
  static public int getMemberCount()  {
    return memberCount; 
  }
  ...
}
final ClubMember
   john = new ClubMember("John"),
  karen = new ClubMember("Karen"),
  petra = new ClubMember("Petra");

System.out.println(karen.getDetails());

System.out.println("Club's member count:"
   + ClubMember.getMemberCount());
// Good: Prevent tampering memberCount
// variable.
Member Karen, member number 2
Club's member count:3
public class Helper {

  public int maximum(int a, int b) {
    if (a < b) {
      return b;
    } else {
      return a;
    }
  }
}
final Helper help = new Helper();

System.out.println("Maximum: " +
            help.maximum(-3, 5));
Maximum: 5

Observation: Instance state irrelevant.

public class Helper {

  static public int
     maximum(int a, int b) {
    if (a < b) {
      return b;
    } else {
      return a;
    }
  }
}
System.out.println("Maximum: " +
     Helper.maximum(-3, 5));
Maximum: 5
Class Variable

{class name}.{variableName}

Class Method

{class name}.{methodName}([parameter])

public class X {
         int a; 
  static int b; 

Variable a defined once per instance of class X.

Variable b defined once per class X.

          
System.out.print(...)

Class System in package java.lang.

Class variable (static) out of type PrintStream in class System

One of 9 overloaded methods in class PrintStream.

  1. Class vs. instance
  2. Distinguishing leap- and non-leap years
  3. A method for printing square numbers using for, while and do ... while
  4. Nicely formatting sine values.
  5. Extending our interest calculator
  6. Integer value considerations.
  7. A class representing fractions
  8. Programmer's favourite expression
  9. Lotteries revisited
  10. Finding the greatest common divisor of two integer values
  • Objects and Classes
    • ➟ Class members and methods
      • ➟ Project dependencies and Maven

        Cross project dependencies.

        Repositories and project artifacts.

Newton's letter
        to Robert Hooke
Project «lottery»
        depending on «helper»
Helper.java pom.xml
package
de.hdm_stuttgart.de.mi.sd1;
public class Helper {
  static public long
    factorial(int n) {
    long result = 1;
    for (int i = 2;
        i <= n; i++) {
      result *= i;
    }
    return result;
  }
}
<project xmlns="http://maven.apache.org...>
 <modelVersion>4.0.0</modelVersion>

 <groupId>de.hdm_stuttgart.de.mi.sd1</groupId>
 <artifactId>helper</artifactId>
 <version>0.9</version>
 <packaging>jar</packaging>
 <name>helper</name>
...
</project>
goik@goiki Helper> mvn install
[INFO] Scanning for projects...
[INFO] -------------------------------------------
[INFO] Building helper 0.9
..
--------------------------------------------------
 T E S T S
--------------------------------------------------
Running de.hdm_stuttgart.de.mi.sd1.HelperTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0,
...
[INFO] Installing .../Helper/target/helper-0.9.jar to
  /ma/goik/.m2/repository/de/hdm_stuttgart/de/mi/sd1/helper/0.9/helper-0.9.jar
goik@goiki tmp> unzip  ...hdm_stuttgart/de/mi/sd1/helper/0.9/helper-0.9.jar
Archive:  .../.m2/repository/.../sd1/helper/0.9/helper-0.9.jar
   creating: META-INF/
  inflating: META-INF/MANIFEST.MF
   creating: de/
   creating: de/hdm_stuttgart/
   creating: de/hdm_stuttgart/de/
   creating: de/hdm_stuttgart/de/mi/
   creating: de/hdm_stuttgart/de/mi/sd1/
  inflating: de/hdm_stuttgart/de/mi/sd1/Helper.class
   creating: META-INF/maven/
   creating: META-INF/maven/de.hdm_stuttgart.de.mi.sd1/
   creating: META-INF/maven/de.hdm_stuttgart.de.mi.sd1/helper/
  inflating: META-INF/maven/de.hdm_stuttgart.de.mi.sd1/helper/pom.xml
  inflating: META-INF/maven/de.hdm_stuttgart.de.mi.sd1/helper/pom.properties
<project ...>
  ...
  <groupId>de.hdm_stuttgart.mi.sd1</groupId>
  <artifactId>lottery</artifactId>
  <version>0.9</version>

  <packaging>jar</packaging>
  <name>lottery</name>

  <dependencies>
    <dependency>
      <groupId>de.hdm_stuttgart.de.mi.sd1</groupId>
      <artifactId>helper</artifactId>
      <version>0.9</version>
    </dependency>
...
</project>
External libraries view
static public long binomial(int n, int k) {
  return (Helper.factorial(n) / Helper.factorial(k)
                              / Helper.factorial(n - k));
}

public static void main(String[] args) {
  System.out.println("There are " + binomial(5, 2) +
      " ways to draw 2 out of 5 numbers");

  System.out.println("There are " + binomial(49, 6) +
      " ways to draw 6 out of 49 numbers");
}
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
Cancelling fractions
  1. Dealing with local Maven dependencies
  2. Maximum and absolute value
  3. Factorial, the direct way
  4. Factorial, the recursive way
  5. Binomials, the recursive way
  6. The exponential f x = e x
  7. Implementing sin ( x ) .
  8. Summing up in a different order.
  9. Transforming arguments.
  • Objects and Classes
    • ➟ Unit testing

      Test categories.

      Why unit testing? Idea of test «driven development».

      Required steps.

  • Unit test: Test individual methods, classes and packages in isolation.

  • Integration Test: Test a group of associated components/classes.

  • Acceptance / Functional Test: Operate on a fully integrated system, testing against the user interface.

  • Regression Test: Ensure system integrity after (implementation) change.

  • Load test: Responsiveness vs. system load.

Informal problem specification:

A prime number is a whole number greater than 1 whose only factors are 1 and itself.

Sample values: 2, 3, 5, 7, 11, 13, 17, 23, ...

layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image

First write tests, then implement.

  1. Specify but not yet implement classes / methods.

  2. Write skeleton (dummy) implementations.

  3. Write corresponding unit tests.

  4. Implement skeleton.

  5. Test your implementation.

  • Objects and Classes
    • ➟ Unit testing
      • ➟ Tests and implementation

        Providing both an implementation and related tests possibly revealing coding flaws.

        Providing prime number related tests.

/**
 * Dealing with prime numbers.
 */
public class Prime {
  /**
   * Check whether a given value is prime or not 
   * @param value A positive value
   * @return true if and only if value is a prime number.
   */
  public static boolean isPrime(int value) {
    return true ; //TODO: Dummy value to be implemented correctly 
  }
}
for (int i = 1; i < 20;i++) {
  System.out.println(i + " is " + (Prime.isPrime(i) ? " a " : " not a ")
    + " prime number");
}
1 is a prime number
2 is a prime number
3 is a prime number
4 is a prime number
5 is a prime number
...
Input Expected output Input Expected output
1 false 7 true
2 true 8 false
3 true 9 false
4 false 10 false
5 true 11 true
6 false 12 false
public class PrimeTest {

  @Test  public void test_1_isNotPrime() {
    Assert.assertFalse(Prime.isPrime(1));
  }
  @Test  public void test_2_isPrime() {
    Assert.assertTrue(Prime.isPrime(2));
  }

  void someOrdinaryMethod()  {...}
...
goik@goiki Prime_v01> mvn test
...
Running de.hdm_stuttgart.mi.sd1.PrimeTest
Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, 
         Time elapsed: 0.065 sec <<< FAILURE!
...
test_1_isNotPrime(de.hdm_stuttgart.mi.sd1.PrimeTest)
         Time elapsed: 0.001 sec  <<< FAILURE!
java.lang.AssertionError
	at org.junit.Assert.fail(Assert.java:86)
	at org.junit.Assert.assertTrue(Assert.java:41)
	at org.junit.Assert.assertFalse(Assert.java:64)
	at org.junit.Assert.assertFalse(Assert.java:74)
...
 skeleton test result (IDE)
@Test public void test_Primes() {
  Assert.assertTrue(Prime.isPrime(3));
  Assert.assertTrue(Prime.isPrime(5));
  Assert.assertTrue(Prime.isPrime(7));
  Assert.assertTrue(Prime.isPrime(11));
    ...  }
@Test public void testOddNonPrimes() {
  Assert.assertFalse(Prime.isPrime(9));
  Assert.assertFalse(Prime.isPrime(15));
  Assert.assertFalse(Prime.isPrime(21));...}
@Test public void testEvenNonPrimes() {
  for (int i = 2; i < 100; i++) {
    Assert.assertFalse(Prime.isPrime(2 * i));
  }
}
public static boolean isPrime(int value) {
  for (int i = 2; i < value; i++) {
    if (0 == value % i) { // i divides value
      return false;
    }
  }
  return value != 1;
}
goik@goiki Prime_v01> mvn test
...
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running de.hdm_stuttgart.mi.sd1.PrimeTest
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.055 sec

Results :

Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
  • Objects and Classes
    • ➟ Unit testing
      • ➟ Improving the algorithm

        Try improving the algorithm.

        Introducing an error.

101 / 2  = 50.5
101 / 3  = 33.6...
101 / 4  = 25.25
101 / 5  = 20.20
101 / 6  = 16.83...
101 / 7  = 14.43...
101 / 8  = 12.625
101 / 9  = 11.2...
101 / 10  = 10.1
101 / 11  = 9.18...
101 / 12  = 8.4...
101 / 13  = 7.7...
...

Big performance gain:

public static boolean isPrime(int value) {
  for (int i = 2; i * i < value; i++) {
    if (0 == value % i) {
      return false;
    }
  }
  return value != 1;
}
Regression test
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
public static boolean isPrime(int value) {

//for (int i = 2; i * i < value; i++) {
  for (int i = 2; i * i <= value; i++) {
    if (0 == value % i) {
      return false;
    }
  }
  return value != 1;
}
  • Objects and Classes
    • ➟ Unit testing
      • ➟ Helpful Junit methods

        Selected assertion methods.

        Considerations when comparing float and double values.

Caution comparing float / double !!
java.lang.AssertionError: Use assertEquals(expected, actual, delta)
  to compare floating-point numbers

at org.junit.Assert.assertEquals(Assert.java:656)
at qq.doubleCompareTest.test1_3(doubleCompareTest.java:15)
...
System.out.println("3.6 - 3 * 1.2 == " + (3.6 - 3 * 1.2));

Result:

3.6 - 3 * 1.2 == 4.440892098500626E-16
public class doubleCompareTest {
  static final double delta = 1E-15;
  /**
   * Comparing 3.6 and 3 * 1.2 within delta's limit
   */
  @Test
  public void test1_3() {
    Assert.assertEquals(3.6, 3 * 1.2 , delta);
  }
}
  1. Summing up integers to a given limit
  2. Summing up, the better way
  • Objects and Classes
    • ➟ Unit testing
      • ➟ Technical details

        Junit Building Blocks: Classes and interfaces

        Integration using Maven.

public
@interface Test {
...
}
  • @interface defining an annotation.

  • Purpose: Adding meta information for automated detection of test methods.

public class Assert {

  public static void assertTrue(
    String message, boolean condition) { ...}

  public static void assertEquals(
    long expected, long actual) { ...}
...
}
<project ...>
...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>

      <scope>test</scope>
    </dependency>
    ...
  </dependencies>
  ...
</project>

Local: /home/goik/.m2/repository/junit/junit/4.12/junit-4.12.jar

Remote: https://mvnrepository.com/artifact/junit/junit/4.12

> jar -tf junit-4.12.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/junit/
...
org/junit/Assert.class
...
  • Objects and Classes
    • ➟ Value types and reference types

      Primitive and value types revisited.

Value type: Holding data in associated memory location
  • byte

  • short

  • int

  • long

  • float

  • double

  • char

  • boolean

Reference type: Holding a reference to an object

Array or class instances i.e. String, java.util.Scanner etc.

Value type
int a = 1;
int b = a;
a = 5;
System.out.println("a=" + a);
System.out.println("b=" + b);
a=5
b=1
Reference type
StringBuffer r = new StringBuffer("Joe");
StringBuffer s = r;
r.append(" Simpson");
System.out.println("r=" + r);
System.out.println("s=" + s);
r=Joe Simpson
s=Joe Simpson
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
public static void main(String[] args) {
  int value = 3;
  System.out.println(
    "Before printDuplicateValue: "
    + value);
  printDuplicateValue(value);
  System.out.println(
    "After printDuplicateValue: "
     + value);
}
static void printDuplicateValue(int n) {
  n = 2 * n;
  System.out.println(
  "printDuplicateValue: " + n);
}
Before printDuplicateValue: 3
printDuplicateValue: 6
After printDuplicateValue: 3
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
public static void main(String[] args) {
  StringBuffer buffer = new StringBuffer("My");
  System.out.println("Before duplicateString: "
    + buffer);
  duplicateString(buffer);
  System.out.println("After duplicateString: "
    + buffer);
}
static void duplicateString(StringBuffer b) {
    b.append(b); // Append self
}
Before duplicateString: My
After duplicateString: MyMy  
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
public static void main(String[] args) {
  StringBuffer buffer = new StringBuffer("My");
  System.out.println("Before duplicateString: "
    + buffer);
  replaceString(buffer);
  System.out.println("After duplicateString: "
    + buffer);
}
static void replaceString(StringBuffer b) {
  b = new StringBuffer("Replacement");
}
Before duplicateString: My
After duplicateString: My
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
// Passing a reference
// to variable n
void printDuplicateValue(int& n) {
  n = 2 * n;
  cout << "duplicateValue: " << n 
       << endl;
}
int main() {
  int value = 3;
  cout << "Before call: "
    << value << endl;
  printDuplicateValue(value);
  cout << "After call: "
    << value << endl;
}
Before call: 3
duplicateValue: 6
After call: 6
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
  • Objects and Classes
    • ➟ Method calls, the details

      Method calls, behind the scenes.

      Stack and heap memory.

      Stack frames and value propagation. Using the debugger.

public class Circle {
  static final double
    PI = 3.141592653589793;
  double r;
  /** Change a circle's area
   *  @param area The desired new area
   *  @return The circle's new radius */
  double setArea(final double area ) {
    double val  = area  / PI ;
    return  r  = Math.sqrt(val);
  }
}

Passing arguments.

Defining method local variables.

Accessing class variable.

returning values.

Accessing instance variable.

public class Circle {

  static final double
    PI  = 3.141592653589793;

  double r  ;

  double setArea(final double area ) {
    double val  ...
    ...
  }
}

Class scope.

Instance scope

Method scope

Class scope (static) Application process
Instance scope Object lifetime: new (...) until being garbage collected.
Method scope Method invocation until return.
Heap memory
  • Allocation of class or array instances:

    new String()
    new float[200]
  • De-allocation subject to garbage collection.

Execution stack
  • One instance per process thread.

  • Hosting variables (values or references)

Method Description Precondition Access type
push(...)

Add object on top

-

Modify

pop()

Read + remove topmost object

Stack not empty

Modify

top()

Read topmost object

Stack not empty

Read only

empty()

true if and only if stack is empty

-

Read only

layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
 debugger
  • Objects and Classes
    • ➟ Enumerations (enum).
  • Modeling finite sets of discrete states.

  • Examples:

    A room's door: {OPEN, CLOSED}

    State of matter: {SOLID, LIQUID, GASEOUS}

  • No dynamic change of state set.

  • Objects and Classes
    • ➟ Enumerations (enum).
      • ➟ Enumeration by integer representation

        Example: Weekdays Monday till Sunday represented by constant int values.

        Common pitfall examples.

        Insufficient means of language protection against self - inflicted problems.

public class Lecture {

    public final int dayHeld; /* e.g. to be held on Tuesdays */

    public final String title; /* e.g. «PHP introduction» */

    public Lecture(final int dayHeld, final String title) {
        this.dayHeld = dayHeld;
        this.title = title;
    }
}

Quick and dirty:

Class Driver:

final Lecture
  phpIntro     = new Lecture(1 /* Monday */, "PHP introduction"),
  advancedJava = new Lecture(5 /* Friday */, "Advanced Java");

Error prone:

  • Weeks start on Mondays?

  • Index starts with 0 or 1?

public class Day {

  static public final int
    MONDAY    = 1,
    TUESDAY   = 2,
    WEDNESDAY = 3,
    THURSDAY  = 4,
    FRIDAY    = 5,
    SATURDAY  = 6,
    SUNDAY    = 7;
}
Class Driver:

final Lecture
  phpIntro     = new Lecture(Day.MONDAY, "PHP introduction"),
  advancedJava = new Lecture(Day.FRIDAY, "Advanced Java");
public class Day {
...
  public static String getDaysName(final int day) {
    switch (day) {
      case MONDAY:    return "Monday";
      case TUESDAY:   return "Tuesday";
      case WEDNESDAY: return "Wednesday";
      case THURSDAY:  return "Thursday";
      case FRIDAY:    return "Friday";
      case SATURDAY:  return "Saturday";
      case SUNDAY:    return "Sunday";

      default:        return "Illegal day's code: " + day;
    }
  }
}
public class Lecture {
  public final int dayHeld;
    ...

  public String toString() {
    return "Lecture «" + title + "» being held each " +
           Day.getDaysName(dayHeld);
  }
}
// Class Driver
final Lecture 

  phpIntro = new Lecture(
    Day.MONDAY, "PHP introduction"),

  advancedJava = new Lecture(
    Day.FRIDAY, "Advanced Java");

System.out.println(phpIntro);
System.out.println(advancedJava);
Lecture «PHP introduction» 
  being held each Monday
Lecture «Advanced Java» 
  being held each Friday
// Class Screwed

final Lecture phpIntro =
    new Lecture(88, "PHP introduction");

System.out.println(phpIntro);
Lecture «PHP introduction» being
held each Illegal day's code: 88
/**
* Charge double prices on weekends
* @param day Day of week
* @param amount
* @return the effective amount for
*         given day of week.
*/
static public int getPrice(
   final int day, final int amount) {
  switch (day) {
    case Day.SATURDAY:
    case Day.SUNDAY: return 2 * amount;

    default: return amount;
  }
}
// Correct
System.out.println(
   getPrice(Day.SUNDAY,  2));

// Argument mismatch
System.out.println(
   getPrice(2, Day.SUNDAY));
4
7

Bad: No warning message whatsoever!

  • Objects and Classes
    • ➟ Enumerations (enum).
      • ➟ Enumeration by dedicated class

        Representing enumeration values by instances gaining type safety.

        Partial problem solution.

Roadmap:

  • Define a dedicated enumeration representing class.

  • Create exactly one class instance per enumeration value.

  • Enumeration value equality comparison by virtue of the == operator.

public class Day {

  static public final Day
    MONDAY    = new Day(),
    TUESDAY   = new Day(),
    WEDNESDAY = new Day(),
    THURSDAY  = new Day(),
    FRIDAY    = new Day(),
    SATURDAY  = new Day(),
    SUNDAY    = new Day();
}

Note: Class without instance attributes.

Reverting to if .. else if ...

public static String getDaysName(final Day day) {
  if (MONDAY == day) {  // Switch no longer possible, sigh!
    return "Monday";
  } else if (TUESDAY == day) {
      ...
  } else if (SUNDAY == day) {
    return "Sunday";
  } else {
    return "Illegal day instance: " + day;
  }
}
/**
 * Charge double prices on weekends
 * @param day Day of week
 * @param amount
 * @return the effective amount depending on day of week.
 */
static public int getPrice(final Day day, final int amount) {
  if (Day.SATURDAY == day || Day.SUNDAY == day) {
    return 2 * amount;
  } else {
    return amount;
  }
}

Preventing method argument order mismatch:

// Class Driver

// o.K.
System.out.println(Screwed2.getPrice(Day.SUNDAY,  2));

// Argument mismatch causing compile time type violation error
System.out.println(Screwed2.getPrice(2, Day.SUNDAY));
Class Screwed:

final Day PAST_SUNDAY = new Day();

final Lecture phpIntro = new Lecture(
     PAST_SUNDAY, "PHP introduction");

System.out.println(phpIntro.toString());
Lecture «PHP introduction» being
held each Illegal day instance: 
de.hdm_stuttgart.mi.sd1.
class_wrapper.Day@63961c42
  • Objects and Classes
    • ➟ Enumerations (enum).
      • ➟ Defining a private constructor

        Clearing the mess.

        Sad: switch still not working.

public class Day {

  // Disallow object creation outside class

  private Day() {} 

  static public final Day
    MONDAY    = new Day(),
    TUESDAY   = new Day(),
  ...
    SUNDAY    = new Day();
}
Class Screwed:

Day PAST_SUNDAY = new Day();

Lecture phpIntro = new Lecture(
     PAST_SUNDAY, "PHP introduction");

System.out.println(phpIntro.toString());

Compile time error:

'Day()' has private access in
'de.hdm_stuttgart.mi.sd1.
class_wrapper_private.Day'
public class Day {
  public final String name;

  private Day(final String name) {
    this.name = name;
  }
  static public final Day
    MONDAY    = new Day("Monday"),
  ...
    SUNDAY    = new Day("Sunday");

    public String toString() { return name; }
}
  • Objects and Classes
    • ➟ Enumerations (enum).
      • enum replacing class

        Introducing enum as kind of restricted class.

        Makes switch working again!

public enum Day {

  MONDAY("Monday"),
  TUESDAY("Tuesday"),
  ...
  SUNDAY("Sunday");

  final String name;
  Day(final String name) { this.name = name;}

  public String toString() { return name;}
}
public enum Day {
...
  public static String getItalianDayName(final Day day) {
    switch (day) {
      case MONDAY:    return "Lunedì";
      case TUESDAY:   return "Martedì";
   ...
      case SUNDAY:    return "Domenica";
    }
    return null; // Actually unreachable, but static
                 // compiler code analysis is limited
  }
}
public enum Day {
  ...
  private Day(final String name)
    { ...

Compile time warning:

Modifier 'private' is redundant for enum constructors

public enum Day {
  ...
  public Day(final String name)
    { ...

Compile time error:

Modifier 'public' not allowed here

Prohibits enum external instance creation.

  1. Compass directions
  2. Compass direction neighbours
  • Objects and Classes
    • ➟ Using git

Git:

  1. A completely ignorant, childish person with no manners.

  2. A person who feels justified in their callow behaviour.

  3. A pubescent kid who thinks it's totally cool to act like a moron on the internet, only because no one can actually reach through the screen and punch their lights out.

  • Objects and Classes
    • ➟ Using git
      • ➟ Working with git locally.

        Creating a git project

        Important commands: git add, git commit, git log, ...

  • git init

  • Result: Sub folder .git containing project's metadata and versioning history

  • public class Math {
    
      static public int add(
       final int a, final int b) {
         return a + b;
      }
    }
  • git status: Math.java yet unversioned.

  • git add Math.java

  • git status: Math.java became versioned.

  • git commit --message "New math class containing single method"

  • Result: Commit change set to repository adding given message to project log.

git status
On branch master 

No commits yet 

Untracked files: 
  (use "git add <file>..." to include in what will be committed)

    Math.java

nothing added to commit but untracked files present (use "git add" to track) 
public class Math {

  static public int add(
   final int a, final int b) {
     return a + b;
  }
}
public class Math {
 /**
  * Summing two int values.
  * @param a first value.
  * @param b second value.
  * @return The sum of both.
  */
  static public int add(
   final int a, final int b) {
     return a + b;
  }
}
git diff tracing changes
>git checkout --  Math.java 

>git diff Math.java 
>

Double dashes '--' disambiguating branch names from file names.

Replace working tree file Math.java by repository master.

No difference working tree to master branch.

> javac Print.java Math.java  # Compilation creating Math.class and Print.class
 
> git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        Math.class
        Print.class

nothing added to commit but untracked files present (use "git add" to track)
  1. Math.class and Print.class are being generated from Math.java and Print.java.

  2. Rule of thumb: Do not version dependent objects.

Solution: Add a .gitignore file to versioning to contain:

# ignore generated .class files
*.class
git log
commit 0137ccd857a242f4751e36bdbce365c6130c3a32 (HEAD -> master) 
Author: Martin Goik <goik@hdm-stuttgart.de>
Date:   Sat May 25 11:56:00 2019 +0200

    Removing duplicate headline 

commit 7f119fac36e02e4c5a7f04f022217b6f744d6e1d 
Author: Martin Goik <goik@hdm-stuttgart.de>
Date:   Sat May 25 11:49:52 2019 +0200

    Project Readme.md  ...
git checkout 7f119fac36e02e4c5a7f04f022217b6f744d6e1d
Note: checking out '7f119fac36e02e4c5a7f04f022217b6f744d6e1d'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 7f119fa Project Readme.md
git checkout master
Previous HEAD position was 7f119fa Project Readme.md
Switched to branch 'master'
git local, DIY
  • Objects and Classes
    • ➟ Using git
      • ➟ Shared development with centralized remote.

        Connecting local to remote repository or clone

        push local to remote

        pull from remote to local

See multi+remote/shared git:

  1. Create empty remote repository on gitlab.mi.hdm-stuttgart.de.

  2. Connect local repository to remote

  3. push or pull content

Step 1: Create remote repository
Step 2: Retrieve remote repository address
git remote add origin  https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git

origin is an alias for our remote repository https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git.

git push --set-upstream origin  master
Username for 'https://gitlab.mi.hdm-stuttgart.de': goik 
Password for 'https://goik@gitlab.mi.hdm-stuttgart.de': 
Counting objects: 5, done.
Delta compression using up to 6 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 507 bytes | 507.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
 * [new branch]      master -> master 
Branch 'master' set up to track remote branch 'master' from 'origin'.
> git pull 
Username for 'https://gitlab.mi.hdm-stuttgart.de': goik 
Password for 'https://goik@gitlab.mi.hdm-stuttgart.de': 
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From https://gitlab.mi.hdm-stuttgart.de/goik/gitintro 
   733e541..ffff092  master     -> origin/master
Updating 733e541..ffff092 
Fast-forward
 Math.java | 10 ++++++++-- 
 1 file changed, 8 insertions(+), 2 deletions(-)
  1. Create new possibly non-empty project at https://gitlab.mi.hdm-stuttgart.de.

  2. > git clone https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
    Cloning into 'gitintro'...
    Username for 'https://gitlab.mi.hdm-stuttgart.de': goik
    Password for 'https://goik@gitlab.mi.hdm-stuttgart.de': 
    remote: Enumerating objects: 5, done.
    remote: Counting objects: 100% (5/5), done.
    remote: Compressing objects: 100% (4/4), done.
    remote: Total 5 (delta 0), reused 0 (delta 0)
    Unpacking objects: 100% (5/5), done.
    
  • Objects and Classes
    • ➟ Using git
      • ➟ Conflicts

        Line level conflicts

        Manual merge

User A: Print.java User B: Print.java
// Driver class
public class Print {
  public static void
    main(String[] args) {
      System.out.println
        (Math.add(2, 3));
  }
}
/**
 * Application entry point
 */
public class Print {
  public static void
    main(String[] args) {
      System.out.println
        (Math.add(2, 3));
  }
}
User A User B
Edit: ... Driver class ... -
git commit, git push -
- edit: ... Application entry point ...
- git commit
- git push: Fail!
>git push ...
To https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to
        'https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
>git pull 
...
From https://gitlab.mi.hdm-stuttgart.de/goik/gitintro
   b003a82..dbbedb0  master     -> origin/master
Auto-merging Print.java
CONFLICT (content): Merge conflict in Print.java
Automatic merge failed; fix conflicts and then commit the result.
>git diff Print.java
diff --cc Print.java
index fc36ae6,7b27edf..0000000
--- a/Print.java
+++ b/Print.java
@@@ -1,6 -1,4 +1,10 @@@
++<<<<<<< HEAD
 +/**                        
 + * Application entry point
 + */
++=======
+ // Driver class 
++>>>>>>> dbbedb0fc29d77beeaaada37f2538d78f82bac93
public class Print {
  public static void
    main(String[] args) {
      System.out.println
        (Math.add(2, 3));
  }
}
Struggling for resolution
<<<<<<< HEAD
/**
 * Application entry point 
 */
=======
// Driver class 
>>>>>>> 10cf21c ... 759462c
public class Print {
  public static void
    main(String[] args) {
      System.out.println
        (Math.add(2, 3));
  }
}
/**
 * Driver class, application entry point 
 */
public class Print {
  public static void
    main(String[] args) {
      System.out.println
        (Math.add(2, 3));
  }
}
>git add Print.java 

>git commit --message "Merging changes" 
[master 173487a] Merging changes

>git push
...
To https://gitlab.mi.hdm-stuttgart.de/goik/gitintro.git
   10cf21c..173487a  master -> master
git distributed, DIY