CPSC 331: Tutorial 1

Introduction, Java Review and Generics

PhD Student

Spring 2018

Introduction

Joshua Horacsek (PhD Student)

joshua.horacsek@ucalgary.ca

MS 625A

These slides will be made available on D2L

Policy:

  • No food or drink
  • Be academically honest
  • Be respectful of your peers

I don't have scheduled office hours, but if you want to chat, just send me an email, I'll try to make it work.

Introduction

Keep in mind this is a Spring course. Things are going to move fast.

Please don't hesitate to ask questions. This material comes up A LOT in practice, it's important for you to learn.

We'll take a 10-15 minute break half way through each tutorial session.

Today

You should have knowledge of Java from a prerequisite course, but I'll try to refresh you on it.

Java Refresher

Java Generics

You should have knowledge of Java from a prerequisite course, but I'll try to refresh you on it.

Break ~ 15min somewhere in there...

Exercises

Some simple exercises to get the juices flowing.

Some Simple Bash

When you log into the ARM server, you'll be presented with a bash (Bourne Again SHell) command prompt. Initially you're in your home directory. Some simple commands are:

  • pwd - prints the current working directory
  • ls - shows the contents of the current directory
  • mkdir - create a new directory
  • cd - change directory
  • rm - remove file

Bash is actually a scripting language, but you'll only need to know basic commands to get by in this course. See this for more info on bash.

Editing Files

Easy mode:

nano filename.c

Productivity mode:

Nano is a barebones text editor, it's great for quick and easy file editing, and has an easier learning curve comapared to emacs.

vim filename.c

Vi (improved) is a text editor that very heavily relies on text commands. It's a bit of an effort to learn, but improves workflow once you've memorized the key commands.

Vim

By default Vim is in command mode:

  • i - changes to insert mode (esc changes to command mode when in insert mode)
  • w - moves the cursor to the next word
  • b - moves the cursor to the previous word
  • u - undo
  • :w - write the file
  • :q - quit
  • ZZ save and quit

Cheat sheet: https://vim.rtorr.com/

When you're in insert mode, type as normal, then esc puts you back in command mode

Java Refresher

Java is a high-level programming language. We try to abstract ourselves away from the machine -- java doesn't care if you're running on an Intel CPU (your desktop) or an ARM CPU (your phone).

main:	
; initializes the two numbers and the counter.  Note that this assumes
; that the counter and num1 and num2 areas are contiguous!
;
	mov	ax,'00'		; initialize to all ASCII zeroes
	mov	di,counter		; including the counter
	mov	cx,digits+cntDigits/2	; two bytes at a time
	cld			; initialize from low to high memory
	rep	stosw		; write the data
	inc	ax		; make sure ASCII zero is in al
	mov	[num1 + digits - 1],al ; last digit is one
	mov	[num2 + digits - 1],al ; 
	mov	[counter + cntDigits - 1],al

	jmp	.bottom		; done with initialization, so begin

Java Refresher

Java is a high-level programming language. We try to abstract ourselves away from the machine -- java doesn't care if you're running on an Intel CPU (your desktop) or an ARM CPU (your phone).

As a high level language, it's easier to express concepts and algorithms.

Java Refresher

Hello World Example

Compile:

/**
 * File: HelloWorld.java
 */

public class HelloWorld{
     public static void main(String []args){
        System.out.println("Hello World");
     }
}

Execute in JVM:

javac HelloWorld.java
java HelloWorld

Java Refresher

Hello World Example

/**
 * File: HelloWorld.java
 */

public class HelloWorld{
     public static void main(String []args){
        System.out.println("Hello World");
     }
}

Execute in JVM:

java HelloWorld

Realistically we'll just do this in Eclipse

Java Refresher

Java is a Object Oriented. We organize concepts as objects. Objects model "real life" phenomena -- although we typically model a small amount of properties/features  we care about.

/**
 * File: Person.java
 */

public class Person{
    private String firstName;
    private String lastName;
    private int age; 
    private int height; 

    public Person(String firstname, string lastname, int age, int height) {
    }

    // getters and setters...
}

Java Refresher

Classes encapsulate the behaviour of objects. This means that other classes shouldn't be aware of the internal structure of a given class. For example:

/**
 * File: Person.java
 */

public class Person{
    private String firstName;
    private String lastName;
    private int age; // <- this is bad design, we have to update it every year
    private int height; 

    public Person(String firstname, string lastname, int age, int height) {
    }
    
    // getters and setters...
    public getAge() {
        return this.age;
    }     
    // getters and setters...
}

Java Refresher

A better design

/**
 * File: Person.java
 */

public class Person{
    private String firstName;
    private String lastName;
    //private int age; // <- this is bad design, we have to update it every year
    private Date dateOfBirth;
    private int height; 

    // We have to keep this constructor around to not break any code that depended on it
    public Person(String firstname, string lastname, int age, int height) {
         // as a hack store today's date minus age, then refactor code to not use this method
    }
    
    // We have to keep this constructor around to not break any code that depended on it
    public Person(String firstname, string lastname, Date dateOfBirth, int height) {
          // fill values
    }

    // getters and setters...
    public getAge() {
        // return difference in years between today and the persons's date of birt
    }     
    // getters and setters...
}

Changing the internals of the class means that most users of the class don't need to change their code

Java Refresher

Classes enforce a hierarchy design via inheritance. I.e we often have is-a relationships between classes for example, a Student is a person, but has a few extra attributes (like a student number)

/**
 * File: Student.java
 */

public class Student extends Person {
    private int studentId;

    public Student(String firstname, string lastname, int age, int height, int sid) {
        super(firstname, lastname, age, height);
        this.studentId = sid;
    }
    
    // getters and setters...
}

A Student object inherits all the methods of a Person, it's a subtype of a Person, whereas a Person is a supertype of student.

Java Refresher

The last fundamental concept in OOP design is polymorphism. Put simply this means that similar objects have the same interface, but perhaps different implementations.

public class Person{
    // properties and methods...

    /* returns an amount of left over food */
    public int eatGivenFood(int amountOfFood) {
        return amountOfFood - 1;
    }
}

public class Student extends Person {
    public int eatGivenFood(int amountOfFood) {
        return 0;
    }
}

Java Generics

Often times, we want to perform the same operations on various different types of data. For example, if I write a method to sort integers, it should be able to sort floating point values.

 

Rather than repeating the code for different types, it is more clean and more maintainable to write code once, and have it work on different types.

This is the problem "Generics" try to solve.

Java Generics

First lets consider an example without generics. Lets say we want to store a pair of values. Without generics this might look like

 

class  Pair {
    Object x; 
    Object y; 
    public  Pair( Object x, Object y ) {
        this.x = x;
        this.y = y;
    }
    public Object getX() { return x; }
    public Object getY() { return y; }
    //...
}

Java Generics

class  Pair {
    Object x; 
    Object y; 
    public  Pair( Object x, Object y ) {
        this.x = x;
        this.y = y;
    }
    public Object getX() { return x; }
    public Object getY() { return y; }
    //...
}

Class usage

Pair pair1 = new Pair(new Integer(1), new Integer(2));
Pair pair2 = new Pair(new Double(2), new Double(2));

// An explicit cast in needed to retrieve a value
int v1    = (Integer)pair1.getX();
double v2 = (Double)pair2.getY();

You have to do all type checking in code -- ideally the compiler should do this.

Java Generics

Let's rewrite the same class with generic parameters. Classes can take a list of parameters between angular <, > braces. 

class  Pair <T1, T2> {
    T1 x; // x is of type T1
    T2 y; // y is of type T2
    public  Pair( T1 x, T2 y ) {
        this.x = x;
        this.y = y;
    }
    public T1 getX() { return x; }
    public T2 getY() { return y; }
    //...
}

Java Generics

class  Pair <T1, T2> {
    T1 x; // x is of type T1
    T2 y; // y is of type T2
    public  Pair( T1 x, T2 y ) {
        this.x = x;
        this.y = y;
    }
    public T1 getX() { return x; }
    public T2 getY() { return y; }
    //...
}

Class usage

Pair <Integer , Integer> pair1 = 
           new Pair<Integer, Integer>(new Integer(1), new Integer(2));
Pair <Double, Double>    pair2 = 
           new Pair<>(0.5, 3.14);  // The compiler infers the omitted types

int    v1 = pair1.getX(); // ok
int    v2 = pair2.getY(); // compile error
double v3 = pair2.getY(); // ok

Java Generics

You can extend generic classes to generic and non-generic classes


import java.lang.*;

class Point extends Pair<Double, Double> {
    public Point(Double x, Double y) {
        super(x,y);
    }

    public double getDistance(Point p2) {
        Double d1 = (this.x - p2.x), d2 = (this.y - p2.y);
        return Math.sqrt(d1*d1 + d2*d2);
    }
}

Java Generics

You can extend generic classes to generic and non-generic classes

class Triple <T> extends Pair <T,T> {
    private T z; // Add another member

    public Triple(T x, T y, T z) {
        super(x,y);
        this.z = z;
    }

    public T getZ() {return z;}
}

Java Generics

Note:

  • Say we have a class Student that is a subtype of the class Person. If we have a generic type List<> it is not true in Java that List<Student> is a subtype of List<Person>
Triple<Integer> tr = new Triple<>(1,2,3);

Pair<Integer, Integer> pr = tr; // This is valid
Triple<Object> tro = tr; // This produces an error

Java Generics

The previous example raises an interesting question, is there a generic type that can be used as a supertype?

 

void printTriple(Triple <?> tr) {
    System.out.println( "" + tr.getX() + ", " +
        tr.getY() + ", " + tr.getZ() )
}

Yes, Java has wildcard types.

You can also impose constraints on wildcard.  I.e. that they must be subtypes or supertypes of a given object.

// Anything that is a subtype of a Person, i.e. student type
List<? extends Person> 

// anything that is a supertype of the Person, i.e. an Animal type,
List<? super Person>   

Java Generics

Methods can also be generic, we could write the printTriple method as 

public  static  <T> void  printTriple( Triple <T> tr ) {
    System.out.println( "" + tr.getX() + ", " +
        tr.getY() +  ", " + tr.getZ() );
}

Java Generics

As an example of a generic method, let's look at Insertion sort (if you haven't learned about Insertion sort yet, it's not a big deal.)

public  <T extends  Comparable <T>> void insertionSort( T[] data ) {
    for(int i = 1, j; i < data.length; i++) {
        T tmp = data[i];
        for(j = i; j > 0 && tmp.compareTo(data[j-1]) < 0; j--)
            data[j] = data[j-1];
        data[j] = tmp;
    }
}

The only requirement for these types of sorting algorithms (exchange sorts) is that we can order items. i.e. they implement the Comparable<T> interface

Java Generics

Caveats

  • Cannot declare static fields whose types are generic
public  class G<T> {
    private  static T var; //not  allowed
}
  • Cannot use primitive types as type parameters             
Triple <int > tr1; // not  allowed
Triple <Integer > tr2; // ok
  • Cannot instantiate generic types in a generic context             
T obj = new T(); // not  allowed
T[] arr = new T[10]; // not  allowed

There are more restrictions, see

https://docs.oracle.com/javase/tutorial/java/generics/

for details.

Generics Exercises

I'm going to give you some exercises and some time, then at the end of the session I'll walk you through my process. 

We'll see how many of them we get through

Generics Exercises

Exercise 1:

We created a generic Pair<T1, T2> class that stored two values of potentially different types. Create a generic Triple class (don't extend the Pair class) that has similar behaviour. You only need to create getters for the class.

Generics Exercises

Exercise 2:

We created a generic Pair<T1, T2> class that stored two values of potentially different types. Create a generic Triple class, by extending Pair, that has similar behaviour. You only need to create getters for the class.

Note we had a similar example before, but it each element in the triple had the same type T

Generics Exercises

Exercise 3:

Suppose we have the classes


abstract class Shape2D {
    abstract public double getArea();
}

class Circle extends Shape2D {
    private double radius;
    public Circle(double radius) { this.radius = radius; }
    public double getArea() { return 3.14 * this.radius * this.radius; };
}

class Rectangle extends Shape2D {
    private double length, width;
    public Rectangle(double len, double width) { this.length = len; this.width = width; }
    public double getArea() { return this.length * this.width; };
}

// Note how this doesn't extend the base Shape2D class
class Triangle  {
    private double base, height;
    public Triangle(double base, double height) { this.base = base; this.height = height; }
    public double getArea() { return this.height * this.base * 0.5; };
}

Create a method that prints the area of any Shape2D subclass. It shouldn't accept Triangle instances.

Generics Exercises

Exercise 4:

Write a method that searches through an array of generic type T. This function should return where the element is in the array. It should return -1 if it can't find the element (or a null value).

Next Week

Victoria Day, Practice Analysis and Correctness

CPSC 331: Tutorial 1

By Joshua Horacsek

CPSC 331: Tutorial 1

  • 1,845