Testing
Thinking Process

Often, development is an incremental process that involves lots of tasks switching and on the fly design modification.
Tests provide stability and scaffolding:
- Provide confidence in basic unitsand mitigate possibility of breaking them.
- Help you focus on one taskat a time.
In large projects, test also allow you to safely refactor (still have the same function)!
Four Philosophies
Here we have four testing philosophies:
- Autograder Driven Development (ADD)
- Unit Tests
- Test-Driven Development (TDD)
- Integration Testing
Autograder Driven Development (ADD)
The worst way to approach programming. This workflow is slow and unsafe!
Wait for the autograder to run, and test everything at the end of development.
Unit Tests

But, how do you test units that rely on others. e.g. how do you test addFirst in Project 1?
Test-Driven Development (TDD)
It is a repeat process consisting of three parts:

Integration Testing
Idea: Tests cover many units at once.
Not JUnit’s focus, but JUnit can do this.
But it tests at highest level of abstraction what may miss subtle or rare errors.

Exercise in Study Guide
| 1 | 
 | 
Inheritance & Implements
Interface & Implementation
Interface Inheritance (what):
- Subclass inherits signatures, but NOT implementation
- So we can also say it is Signature Inheritance.
Implementation Inheritance (how):
- Subclasses can inherit signatures AND implementation.
Static vs. Dynamic Type
Every variable in Java has a compile-time type, a.k.a. static type.
- This is the type specified at declaration. Never changes!
Variables also have a run-time type, a.k.a. dynamic type.
- This is the type specified at instantiation(e.g. when usingnew).
- Equal to the type of the object really being pointing at.

| 1 | Animal a = new Animal("Pluto", 10); | 
If Y overrides the method, Y’s method is used instead. This is known as dynamic method selection.
Implementation inheritance may sound nice, but there are some drawbacks:
- We are fallible humans, and we can’t keep track of everything, so it’s possible that you overrode a method but forgot you did.
- It may be hard to resolve conflicts in case two interfaces give conflicting default methods.
- It encourages overly complex code.
Encapsulation
When building large programs, our enemy is complexity.
Ways of managing complexity (ultimately determine whether a programmer is successful), as shown in Software Engineering lectures:
- Hierarchical abstraction(List, LinkedList, ArrayList)
- Design for (future) change(D. Parnas)- Organize program around objects(modules)
- Let objects decidehow things are done. Outsider needs not to know.
- Hide informationothers don’t need (helper functions)
 
- Organize program around 
Even when writing tests, you don’t (usually) want to peek inside.
Ideally, a user should not be able to observe the internal workings of, say, a data structure they are using. Java is a great language for enforcing abstraction barriers with syntax (language aspect).
Later, we use Abstract Data Types (ADTs) to handle what we need.
Inheritance Breaks Encapsulation:
1st Implementation:
(The upper box is in superclass)

2nd Implementation (Really bad):

By allowing inheritance in a particular situation, we now have a way to peek inside a beautifully encapsulated class.
We didn’t change anything in overridden barkMany, but someone changed the superclass implementation that they thought it was safe and kapow (爽).
Type Checking & Casting
Type Checking
Static type is also called compile-time type.
Override:
If a method in SLList is overridden by the VengefulSLList class, then the method that is called at runtime is determined by the run-time type (dynamic type) of that variable (dynamic method selection).
- If a method overridden: Call fromdynamic type.
- If a method not overriden: Call fromstatic type.
| 1 | /** | 
Compiler is conservative in type checking.
| 1 | /* Compile-time Error */ | 
In general, the compiler only allows method calls and assignments based on compile-time types.
| 1 | VengefulSLList<Integer> vsl2 = sl; | 
Also, expressions using the new keyword also have compile-time types.
| 1 | VengefulSLList<Integer> vsl = new SLList<Integer>(); | 
Above, the compile-time type of the right-hand side of the expression is SLList. The compiler checks if SLList “is-a” VengefulSLList, which it is not in all cases, and thus a compilation error results.
Further, method calls have compile-time types equal to their declared types. Suppose we have this method:
| 1 | public static Dog maxDog(Dog d1, Dog d2) { ... } | 
Casting
Java has a special syntax where you can tell the compiler that a specific expression has a specific compile-time type. This is called casting. With casting, we can tell the compiler to view an expression as a different compile-time type, ignoring its type checking duties.
| 1 | // Pass type checking in compile time. | 
Should be careful when doing downcasting, especially when downcasting a superclass to a subclass.
| 1 | /* The problem lies in the right hand side. */ | 
It’s okay if we are sure that the object whose static type is superclass actually has a subclass dynamic type.
| 1 | Animal a = new Dog(); | 
Method Preferences
Example 0:
| 1 | Dog d = new Dog(); | 
((Animal) d).makeNoise(d): In compile-time type checking, when checking to see if a method called makeNoise exists in Animal, do we check for a makeNoise(Dog) method or a makeNoise(Animal) method?
- Compile time (Animal):- Check method name-> matched
- Check parameter types-> It depends the methods in Animal class.- It can match Animal’s makeNoise(Animal)
- Or match makeNoise(Dog)
- But it will definitely goes for the later one because it is a more specific match.
 
- It can match Animal’s 
 
- Check 
- Run time (Dog):- dis a Dog, not an Animal.
- If the method is overridden?- Yes. Call the overridden version. (Dynamic Method Selection)
- No. Call the superclass version.
 
 
Idea:
- Parameter type-checking prefers specificif possible.
- The order is important:- Class typeChecking:- Static type == Dynamic type: - Override won’t happen. Overload may happen.
 
- Static type != Dynamic type: - If the method is overridden -> dynamic method selection.
- If not -> just call the one matched in superclass.
 
 
- Static type == Dynamic type: 
 
- The method we consider later in run time is the one decidedin compile-time type checking.- In run time, it won’t change its mind from makeNoise(Dog)tomakeNoise(Animal).
- In run time, we check if this method is overridden to decide if we need dynamic method selection.
 
- In run time, it won’t change its mind from 
Consider the two examples (Very important):
Example 1:
| 1 | class Animal { | 
Line 1:
- Compile time (Animal):- Check method name-> matched
- Check parameter types-> compatible (Dog is an Animal), matched
 
- Check 
- Run time (Dog):- ais Dog. The method- makeNoise(Animal)is overridden. So it outputs “Dog1”.
 
Line 2:
- Compile time (Animal):- Check method name-> matched
- Check parameter types-> exactly matched
 
- Check 
- Run time (Dog):- ais Dog. The method- makeNoise(Animal)is overridden. So it outputs “Dog1”.
 
Example 2:
| 1 | class Animal { | 
Line 1:
- Compile time (Animal):- Check method name-> matched
- Check parameter types-> prefer specific version, exactly matched (makeNoise(Dog)).
 
- Check 
- Run time (Dog):- ais Dog. The method- makeNoise(Dog)is overridden (not overloaded). So it outputs “Dog2”.
 
Line 2:
- Compile time (Animal):- Check method name-> matched
- Check parameter types-> exactly matched
 
- Check 
- Run time (Dog):- ais Dog. The method- makeNoise(Animal)is overridden. So it outputs “Dog1”.
 
Higher Order Functions (HoFs)
Higher Order Function: A function that treats another function as data (or input?).
| 1 | # In Python | 
In old school Java (Java 7 and earlier), memory boxes (variables) could not contain pointers to functions. What that means is that we could not write a function that has a “Function” type, as there was simply no type for functions.

In Java, we can use Interface to do this. Use a Interface class to wrap up a method / function.
Interface:
| 1 | public interface IntUnaryFunction { | 
Implementation:
| 1 | public class TenX implements IntUnaryFunction { | 
Using:
| 1 | // Use Interface IntUnaryFunction rather than TenX - Abstraction | 
Ex (Examprep 4)
Ex 1 (Puppers)
| 1 | public class Dog { | 
For the following main method, at each call to play or bark, tell us what happens at runtime by selecting which method is run or if there is a compiler error or runtime error.
| 1 | public static void main(String[] args) { | 
Ex 2 (Cast the line)
Consider each line independently whether it causes a compilation error, runtime error, or runs successfully.
| 1 | // Animal Tree | 
Ex 3 (SLList Vista)
indexOf:
| 1 | // IntList class: | 
Polymorphism vs. HoFs
Polymorphism
Polymorphism, at its core, means many forms. In Java, polymorphism refers to how objects can have many forms or types.
In object-oriented programming, polymorphism relates to how an object can be regarded as:
- an instance of its own class,
- an instance of its superclass,
- an instance of its superclass's superclass,
- and so on.
The above statement is very great.
Subtype Poly. vs. HoF
Explicit HoF Approach:
| 1 | def print_larger(x, y, compare, stringify): | 
Subtype Polymorphism Approach:
| 1 | def print_larger(x, y): | 
In Python or C++, the way that the > operator works could be redefined (overloaded) to work in different ways when applied to different types. 
Unfortunately, Java does not have this capability. Instead, we turn to interface inheritance to help us out. We do this by wrapping up the needed function in an interface (e.g. Arrays.sort needs compare which lives inside the comparator interface). Arrays.sort “calls back” whenever it needs a comparison.
| 1 | public interface OurComparable { // should be "extends Comparable"? | 
So we can generalize the max function.
| 1 | /* Maximizer class */ | 
What are the benefits to this approach?
- No need for maximization code in every class (i.e. no Dog.maxDog(Dog[])function required.- We don’t need to know that class should be Dog class.
 
- We have code that operates on multiple types (mostly) gracefully
Easy Quizzes:


Comparable
The OurComparable interface that we just built works, but it’s not perfect. Here are some issues with it:
- Awkward castingto/from Objects- 1 
 2
 3
 4- public int compareTo(Object o) { // or Comparable 
 Dog uddaDog = (Dog) o; // casting
 return this.size - uddaDog.size;
 }
- We made it up.- No existing classes implement OurComparable(e.g. String, etc.)
- No existing classes use OurComparable(e.g. no built-in max function that uses OurComparable)
 
- No existing classes implement 
The solution? We’ll take advantage of an interface that already exists called Comparable. Comparable is already defined by Java and is used by countless libraries.
Comparable looks very similar to the OurComparable interface we made, but with one main difference.
| 1 | public interface Comparable<T> { | 
The generic type will help us avoid casting an object to a specific type.
Comparator
Let’s start off by defining some terminology.
- Natural order- used to refer to the ordering implied in the- compareTomethod of a particular class. (Dog - size)
What if we’d like to sort Dogs in a different way than their natural ordering, such as by alphabetical order of their name?
In explicit HoF approach, we can use compare to specify a different compare function. However, in subtype polymorphism approach, compareTo1, compareTo2, and so forth? No!
| 1 | def print_larger(T x, T y, comparator<T> c): | 
Java’s way of doing this is by using Comparator‘s. Since a comparator is an object, the way we’ll use Comparator is by writing a nested class (so it’s static) inside Dog that implements the Comparator interface.
Note: It is static because we don’t need to instantiate a Dog to get a NameComparator. Instead, we get it when initializing the class.
| 1 | public interface Comparator<T> { | 
Now, the Dog class should be like:
| 1 | import java.util.Comparator; | 
In DogLauncher, the code is:
| 1 | Dog.NameComparator nc = Dog.getNameComparator(); | 
In summary, a Comparable says, “I want to compare myself to another object”. It is imbedded within the object itself, and it defines the natural ordering of a type.
However, a Comparator, on the other hand, is more like a third party machine that compares two objects to each other. Since there’s only room for one compareTo method, if we want multiple ways to compare, we must turn to Comparator.
Abstract Data Types (ADT)
Interface
In Java, Deque is called an interface. Conceptually, we call deque an Abstract Data Type. Deque only comes with behaviors, not any concrete ways to exhibit those behaviors. In this way, it is abstract.
Stack: LIFO propertyQueue: FIFO propertyDeque: Both LIFO and FIFO
In Java, we use interfaces to achieve ADTs:
- Cannot be instantiated.
- Can provide either abstractorconcretemethods.- Use defaultkeyword for concrete methods.
 
- Use 
- Can provide only public static finalvariables.
- Can provide only publicmethods.
| 1 | // In an interface class | 
Abstract Class

Abstract class doesn’t have to implement the method listed in interface.
Interface vs. Abstract Class
Interfaces:
- Primarily for interface inheritance. Limited implementation inheritance.
- Classes can implement multiple interfaces. (main difference)
Abstract classes:
- Can do anything an interface can do, and more.
- Subclasses only extend oneabstract class.
List Hierarchy

Why didn’t we use Interface only?
AbstractList provides default implementations for methods. But why not just put them in List itself? No default methods in Java interfaces until 2014, and the AbstractList was public so we can’t just throw it away.
A more of the real list hierarchy:

Even more:

When in doubt, try to use interfaces in order to build up abstraction, reduce complexity, and hide unnecessary information.
Discussion 5:
Some scenes of application:
- Given a news article, find the frequency of each word used in the article: - Use a - map.
- Given an unsorted array of integers, return the array sorted from least to greatest: - Use a - priority queue. For each integer in the unsorted array, enqueue the integer with a priority equal to its value.
- Implement the forward and back buttons for a web browser: - Use two stacks, one for each button. Each time you visit a new web page, add the previous page to the back button’s stack, and also clear the forward button stack.- When you click the back button, add the current page to the forward button stack, and pop a page from the back button stack. - When you click the forward button, add the current page to the back button stack, and pop a page from the forward button stack. 
Ex (Discussion 5)
Ex 1 (Queue)
Two-Stack Version
| 1 | public class Queue { | 
A Stack can also be implemented by two Queues.
Recursive Version
| 1 | public class Queue { | 
Ex 2 (TwoSum)
Given an array of integers $A$ and an integer $k$, return true if any two numbers in the array sum up to $k$, and return false otherwise. How would you do this? Give the main idea and what ADT you would use.
Brute-force: 2 loops.
A smarter way (use a map):
| 1 | public boolean twoSum(int[] A, int k) { | 
Ex 3 (K-most Words)
Find the k-most common words in a document. Assume that you can represent a string as an array of words, where each word is an element in the array. You might find using multiple data structures useful.
Keep a count of all the words in the document using a HashMap<String, Integer>. After we go through all of the words, each word will be mapped to how many times it’s appeared.
Then we can put all the words into a MaxPriorityQueue<String>, using a custom comparator that compares words based on the counts in the HashMap. We can then pop off the k-most common words by just calling poll() on the MaxPriorityQueue k times.
| 1 | public static void topFivePopularWords(String[] words, int k) { | 
Ex 4 (SortedStack)
Suppose we wanted a data structure SortedStack that takes in integers, and maintains them in sorted order. SortedStack supports two operations: push(int i) and pop(). Popping returns the next smallest item in the SortedStack.
For example, if we inserted [10, 4, 8, 2, 14, 3] into a SortedStack, and then popped everything off, we would get [2, 3, 4, 8, 10, 14].
My Way
Not using stacks (iterative way). We have some invariants:
- The smallest item is at the top of stack.
- Push guarantees that the items in stack is in increasing order.
| 1 | public class SortedStack() { | 
Answer
Using stacks:
We have two stacks A and B. A holds all the items, and B is our buffer.
| 1 | public class SortedStack<Item extends Comparable<Item>> { | 
Package
Package names give a canonical name for everything. “Canonical” means a unique representation for a thing.
Importing Class
Here are some different ways we can use a class:
- Entire name.1 ug.joshh.animal.Dog d = new ug.joshh.animal.Dog(); 
- Can use import statement to provide shorthand notation for usage of a single class in a package.1 
 2import ug.joshh.animal.Dog; 
 Dog d = new Dog();
- Wildcard import: Also possible to import multiple classes, but this is often a bad idea!1 
 2import ug.joshh.animal.*; 
 Dog d = new Dog();
Import static members:
| 1 | import static org.junit.Assert.assertEquals; | 
The built-in java.util package provides a number of useful interfaces and implementations.
Creating A Package
The reason why we use Package is to address the fact that classes might share names. A package is a namespace that organizes classes and interfaces.
Naming convention: Package name starts with website address (backwards).
| 1 | package bearmaps.hw4.wordladderpuzzle; | 
Two steps:
- At the topof every file in the package, put the package name.
- Make sure that the file is stored in a folder with the appropriate folder name. For a package with name ug.joshh.animal, use folderug/joshh/animal.
The Default Package
Any Java class without a package name at the top are part of the default package. In other words, from now on, when writing real programs, your Java files should always start with a default package declaration.
Idea: Ensure that we never have two classes with the same name at any situation.
But, you cannot import code from the default package! For example, if I were to create a DogLauncher class in the default package in a DogLauncher.java file, I would be unable to access this DogLauncher class anywhere else outside of the default package.
| 1 | package cat.place; | 
JAR Files
JAR file are just zip files.
- They do not keep your code safe!
- Easy to unzip and transform back into .Java files (from .class).
Note: Do not share .jar files of your projects with other students.
Ex (Guide)
Ex 1 (Q&A)
- If an - abstract classextends an- abstract class, would it need to have function definitions for the abstract methods in the parent class? Similarly would an- interfacethat implements another- interfacehave to implement the non-default methods in the parent interface.- No. No. If not implementing in the subclass or subinterface, the sub-subclass or sub-subinterface should do the job. 
- Can an - abstract classbe the subclass of a- normal class?- Yes. (The default package) 
Ex 2 (Same Method Name)
Consider the following code:
| 1 | class Tree { | 
The output is:
| 1 | haha - Dog | 
Autoboxing
How it works (wrapper type and primitive type):
- If Java code expects a wrapper type and gets a primitive, it is autoboxed.
- If the code expects a primitive and gets a wrapper, it is unboxed.
| 1 | /* Not a magic */ | 
Note:
- Arrays are never autoboxed/unboxed, e.g. an Integer[]cannot be used in place of anint[](or vice versa).
- Autoboxing / unboxing incurs a measurableperformance impact!
- Wrapper types use muchmore memory than primitive types because of object overheads.
Space occupied:
- Addresses are 64 bits.
- ints are 32 bits.
- All Java objects take 64 bits + their fields.
| 1 | public static void bleepblorp() { | 
Access Control
Access Modifier
How do public and private behave with packages and subclasses?

- Public: This keyword opens up the access to everyone! This is generally what - clientsof the package can rely on to use.- Once deployed, the public members’ signatures should not change. It’s like a promiseandcontractto people using this public code that it will always be accessible to them.
- Usually if developers want to “get rid of” something that’s public, rather than removing it, they would call it deprecatedinstead.
- TL;DR: Open and promised to the world.
 
- Once deployed, the public members’ signatures should not change. It’s like a 
- Protected: Protected members are protected from the - outsideworld.- Classes within the same packageandsubclassescan access these members, but the rest of the world (e.g. classes external to the package or non-subclasses) cannot!
- TL;DR: Subtypes might need it, but subtype clients will not.
 
- Classes within the 
- Package Private: This is the default access given to Java members if there is no explicit modifier written. - Package private entails that classes that belong in the same package can access, but not subclasses!
- The original owners of the class that’s being extended may not want certain features or members to be tampered with, if people choose to extend it — hence, package-private allows those who are familiar with the inner workings of the program to access and modify certain members, whereas it blocks those who are subclassing from doing the same.
- TL;DR: Only classes that live in the same package can access.
 
- Private: Only code from the - given classcan access private members.- It is truly private from everything else, as subclasses, packages, and other external classes cannot access private members.
- TL;DR: Only the class needs this piece of code.
 
| 1 | package syntax3.map; | 
Subtleties:
Interface methods are public in default.

Nested class
| 1 | public class Outer { | 
In the example above: Anybody can create an Outer, anybody can create an Inner, and anybody can access an Inner’s variable. And an Inner can access this.outvar.
| 1 | public class Outer { | 
In the example above, Inner is private. At this point, the access modifiers to all of inners’ members are irrelevant.
- An Outer can accessan Inner’s variables. The reason is that “Inner” is a subordinate slave of Outer, and thus has no personal possessions.
- We can change public (invar) to anything and have no observable effect (its function has been shadowed).
- Classes other than Outer cannot make or access Inner anymore. Common for things like LinkedListDeque (make your IntNode class private).
| 1 | public class Outer { | 
In the example above, can an Inner access an Outer’s outvar? Yes, it can because Inner is part of the Outer class.
What could I do so that an Inner can’t use outvar?
| 1 | public class Outer { | 
Can I instantiate a non-static inner class (nested class) without an outer instance?
| 1 | /** 1 */ | 
Discussion 6
Exception
There are 2 overarching types of exceptions:
- Checked - You must either wrap them in a - try/catch blockor pass the buck by using- throws exceptionin the method header.
- Unchecked - You don’t need to handle these. They are typically an error on a user’s part, which can’t really be helped. 

Iterators and Iterables

Ex (Discussion 6)
Ex 1 (AltList)
| 1 | public AltList<X, Y> pairSwapped() { | 
Ex 2 (Every K-th Element)

| 1 | public class KthIntList implements Iterator<Integer> { | 
