# 11: End-of-Project-1 Review (Java, Patterns, Testing, etc.)
###### tags: `Tag(sp22)`
## Reading The Notes After Lecture?
I never said what "PECS" stands for! It stands for...
* Producer: `extends`.
* Consumer: `super`.
## Logistics and Preview
* Based on hours discussions and feedback, we're rearranging Sprint 3 (which will still be released later this week). Highlights:
* React will be in Sprint 4, not Sprint 3.
* ...so I won't be talking about React today.
* We'll push the React lab to next week.
* There will be no lab this week.
* **Class next Thursday: Emmanuel Schanzer guest lecture**! Don't miss it if you're able to attend. **Show our hospitality: don't miss Emmanuel's talk, and ask him questions!**
* I'm holding an extra OO/Java recitation section tomorrow (Wednesday) at 1pm, in my [Zoom](https://cs.brown.edu/~tbn/zoom.txt).
Today will be several cross-cutting exercises and discussions that will be useful, either for general (debugging!) or specific Sprint 2 (generics) reasons. I've tried to address various questions I've gotten but haven't been able to discuss in class.
## Investigating Bugs: JavaScript
There was a coda to last Thursday's lecture notes involving a puzzling behavior at the JavaScript console. I want to run through it, because it demonstrates how subtle debugging can be. (If you have read the notes and recall the example, don't spoil it for others!)
### Debugging In The Console
Many functions you call in JavaScript are asynchronous.
There are also some behaviors that can look asynchronous but are tangled with other issues. Here's a great example that we can run in the browser console:
```javascript
var arr = [0,1,2]
for(var i = 0; i<arr.length;i++) {
arr[i] = -1;
console.log(arr);
};
```
Here's the output in the console:
```
Array(3) [ -1, 1, 2 ]
Array(3) [ -1, -1, 2 ]
Array(3) [ -1, -1, -1 ]
```
But if I click the arrow to expand the first array:
```
Array(3) [ -1, 1, 2 ]
0: -1
1: -1
2: -1
length: 3
<prototype>: Array []
```
What's going on here? It looks like concurrency could be involved, because we see an apparent delay in the effect of the `for` loop's assignment statements.
<details>
<summary>Think, then click!</summary>
This behavior isn't about whether a call is asynchronous. Rather, it's about how the *console itself* works. When we print out an object with `console.log`, it prints the object summary, but gives us the option of "clicking in" for more details. How does the console do this? It wouldn't be efficient to pre-expand the object and store a string---instead, it probably stores a reference to the object.
That's why expanding the array shows different values than the summary. This apparent "delay" isn't about concurrency at all; it's about how the browser console is implemented.
</details>
### Confirming The Hypothesis
Suppose we add a little bit more:
```javascript
var arr = [0,1,2]
for(var i = 0; i<arr.length;i++) {
arr[i] = -1;
console.log(arr);
};
arr = [0, 0, 0];
console.log(arr);
for(var i = 0; i<arr.length;i++) {
arr[i] = 10;
console.log(arr);
};
```
If our hypothesis above were correct, what would we expect to see?
<details>
<summary>Think (and experiment!) then click!</summary>
When we re-assign `arr` to a _new_ array, the second `for` loop is modifying that array, not the old one. So there are now two distinct references that the console keeps. We'd like the first 3 console entries to expand to show `-1` but the 4 later entries to all show `10`.
</details>
**Takeaway:** If you're dealing with a subtle bug that you can't understand by itself, make small changes locally to make sure you understand what's really going on. **This principle applies in _any_ programming language.**
## Back to Java: `static`
The `static` keyword in Java has (at least) 4 different contexts. They all relate to whether data, or computation, are associated with a _class_ or with an _object_.
### Static Fields
```java
class ThingCounter {
private static long counterForClass = 0;
private long counterForObject = 0;
void increment() {
counterForObject++;
counterForClass++;
}
public long counter() {
return counterForObject;
}
public long allCounter() {
return counterForClass;
}
}
class CounterDemo {
public static void main(String[] args) {
ThingCounter c1 = new ThingCounter();
ThingCounter c2 = new ThingCounter();
c1.increment();
c2.increment();
System.out.println(c1.counter());
System.out.println(c2.counter());
System.out.println(c1.allCounter());
System.out.println(c2.allCounter());
}
}
```
Static fields are useful if you want to have some canonical value or reference shared by all instances of a class.
### Static Code Blocks
If you want to write code that executes as part of the initialization of a _class_, you can add a static block:
```java
public class StaticBlockDemo {
static {
System.out.println("Class is loading (executes only once)...");
}
public static void main(String[] args) {
System.out.println("Main is invoked...");
}
}
```
You won't see static blocks often. When you do, it may be related to loading external native-code libraries, or setting up special classes that should only ever be instantiated once. You can also use it to ensure assignment of `final static` fields in a class.
### Static Methods
A static method in Java belongs to the class, rather than to an instance of the class. You see this most commonly in the `main` method, which is an entry point into the program. If I instantiate the class that contains the `main` method, there is still only one `main` method to call.
```java
public class Main {
public static void hi() {
System.out.println("hi");
}
public static void main(String[] args) {
Main m1 = new Main();
Main m2 = new Main();
hi();
Main.hi();
m1.hi();
m2.hi();
}
}
```
All 4 calls here work, and refer to the same `hi` method. IntelliJ warns us that the last 2 calls are suspicious:
```
Static member 'edu.brown.cs32.livecode.mar08.Main.hi()' accessed via instance reference
```
Static methods are often used to build factories, which separate out the creation of a class from that class itself (e.g. `Collections.unmodifiableMap`) or utility methods that work with a class without being defined within it (e.g., `Arrays.toString`).
### Static Member Classes
Finally, you'll sometimes see the `static` keyword used on _classes_. You can only apply it to a _member_ class (a class defined within another class, also sometimes called a _nested_ class). It means that the member class cannot refer to members of its enclosing class. E.g., this gives an error:
```java
public class StaticClassDemo {
int value = 0;
static class Inner {
value++;
}
}
```
You can read more about the static keyword and static classes in Effective Java. **Non**-static member classes are often good for implementing the adapter pattern (e.g., iterators). **Static** member classes are good for class-internal data storage that doesn't require access to the enclosing class instance (e.g., the node objects in a tree data structure).
## Break!
This is a good time for a break.
## A Generics Exercise
Which of these 4 commented-out statements will have an error?
```java
public class GenericsExercise1 {
public static void main(String[] args) {
Collection<Number> someNums = new HashSet<>();
someNums.add(1); // setup (works)
someNums.add(1.5); // setup (works)
someNums.add(null); // setup (works)
// Bounded wildcard: any subtype of Number
Collection<? extends Number> someNums2 = new HashSet<>();
// Which of these will be OK?
//someNums2.add(1); // ?
//someNums2.add(1.5); // ?
//someNums2.add(null); // ?
//someNums2 = someNums; // ?
System.out.println(someNums2);
}
}
```
<details>
<summary>Think, then click!</summary>
The first two (adding `1` and adding `1.5`) both give an error. The second two (adding `null` and assigning the reference in `someNums` to `someNums2` don't produce an error).
</details>
**Why do you think this is?**
<details>
<summary>Think, then click!</summary>
The trick is that a generic type variable, whether a wildcard or something with a name, like `T`, corresponds to _one type_. The bounded wildcard `? extends Number` means "some single subtype of `Number`", and so a collection of `? extends Number` _is not_ a collection of _different_ kinds of `Number`. It's a collection of some single specific type of `Number`. The compiler doesn't know what kind of `Number` the collection contains, and so we can't add either of those subtypes of `Number`.
In contrast, we can _extract_ elements of `someNums2` as `Number`s:
```
for(Number n : someNums2)
System.out.println(n);
```
Why does `null` work? After all, `null instanceof Number` evaluates to `false`. It works for the same reason you can say `Number n = null;` in Java: a `null` has no runtime class, but at compile time it only represents the absence of data.
</details>
## Another Generics Exercise
First, I want to show you that generic type variables can indeed be introduced for a single method, using this syntax:
```java
public static <T extends Comparable<T>> void filterLowerThan(Collection<T> a, T value) {
a.removeIf(b -> b.compareTo(value) < 0);
}
```
The `<T extends Comparable<T>>` is not a return type (that's `void`), but an introduction of the bounded type variable `T`.
Now let's try an exercise:
```java
class Stack<E> {
List<E> actual = new ArrayList<>();
public void push(E element) {
actual.add(0, element);
}
public E pop() {
E element = actual.get(0);
actual.remove(0);
return element;
}
// What's wrong with this method's type?
public void pushAll(Set<E> elements) {
for(E e : elements)
push(e);
}
// What's wrong with this method's type?
public void popAll(Collection<E> destination) {
for(E e : actual) {
destination.add(e);
}
}
}
```
What's wrong here? (There are no compiler errors.)
<details>
<summary>Think, then click!</summary>
Similarly to other generics exercises we've run, let's try something like this:
```java
public static void main(String[] args) {
Set<Number> nums = new HashSet<>();
Set<Integer> ints = new HashSet<>();
Stack<Number> stack = new Stack<>();
stack.pushAll(nums);
stack.pushAll(ints);
stack.popAll(nums);
stack.popAll(ints);
}
```
</details>
</br>
Ok, but now let's _fix_ the problem. Surely the `main` code above is something we'd like to enable about our stack. A caller will be very unhappy if they need to typecase `Integer`s to `Number`s in order to use our data structure.
### Fixing The Problem: The **PECS** Rule
How can we fix the types of those 2 methods? Let's start with `pushAll`.
<details>
<summary>Think, then click!</summary>
For `pushAll`, the problem is that we need to be able take a set `elements` that **produces** elements of some subtype of `E`. So we'll say:
```java
public void pushAll(Set<? extends E> elements) {
for(E e : elements)
push(e);
}
```
</details>
For `popAll`, will the same fix work?
<details>
<summary>Think, then click!</summary>
No. We don't really want something that **produces** elements of a subtype of `E`. Instead, we want something that can **consume** elements of a subtype of `E`.
```java
public void popAll(Collection<? super E> destination) {
for(E e : actual) {
destination.add(e);
}
}
```
To see why, suppose our `Stack` stores `Number`s, and follow the chain of logic.
</details>
</br>
I always have to think through `? super E` and remind myself why it's even a thing. We need it here because we need to be certain that it's safe to add an element to the consumer class. This is only true if its type parameter is an *ancestor* of `E`! E.g., we can plug any kind of `Number` into (e.g.) an Object, but not into (e.g.) an Integer.
## Potential Future Topics Include
Future topics:
* dynamic vs. static dispatch
* microbenchmarking and profiling
* reviewing how to use dependency injection with the REPL
* dangers: handling memory in your cache
* ...