---
# System prepended metadata

title: Java Programming 2 - Generics
tags: [' generics', java]

---

---
title: Java Programming 2 - Generics
tags: java, generics
---

# Java Generics

### References
* https://courses.cs.washington.edu/courses/cse331/18wi/lectures/lec13-generics.pdf
* https://www.oracle.com/technetwork/articles/java/juneau-generics-2255374.html
* https://www.journaldev.com/1663/java-generics-example-method-class-interface

## Why We Need Generics?
* For example, we consider a collection of books like this:
    ```java=
    public class BoxOfBooks {

        private Book[] books;

        public BoxOfBooks(int size) {
            books = new Book[size];
        }

        public Book get(int idx) {
            Book output = books[idx];
            books[idx] = null;
            return output;
        }

        public void add(int idx, Book book) {
            books[idx] = book;
        }

    }
    ```
* Now we consider another collection, say toys:
    ```java=
    public class BoxOfToys {

        private Toy[] toys;

        public BoxOfToys(int size) {
            toys = new Toy[size];
        }

        public Toy get(int idx) {
            Toy output = toys[idx];
            toys[idx] = null;
            return output;
        }

        public void add(int idx, Toy toy) {
            toys[idx] = toy;
        }

    }
    ```
* Stop!!! **Don’t repeat yourself!**
    ```java=
    public class Box<T> {

        private T[] items;

        public Box(int size) {
            items = (T[]) new Object[size]; // Why this works?
        }

        public T get(int idx) {
            T output = items[idx];
            items[idx] = null;
            return output;
        }

        public void add(int idx, T item) {
            items[idx] = item;
        }

    }
    ```
* So we can store books and toys by using this **generic class**.
    * You may see Jave Generics widely used in Java Collections.
        ```java=
        public class GenericsDemo1 {

            public static void main(String[] args) {

                Box<Book> c1 = new Box<>();
                c1.add(new Book("Java Programming 2"));

                Box<Toy> c2 = new Box<>();
                c2.add(new Toy("Snoopy"));

            }

        }
        ```
* In this way, we could **reuse** our codes, just like what we learned before.
    * For example, loops, methods, and inheritance in OOP.

## Syntax of Generic Classes
* To declare the **type parameters**, we put these type variables in a pair of angle brackets <>.
    ```java=
    class ClassName<T1, T2, ...> {}
    interface InterfaceName<T1, T2, ...> {}
    ```   
    * For example, 
        ```java=
        public interface List<E> {

            E get();
            void add(E e);

        }
        ```
    * Another example shows how to declare multiple type parameters.
        ```java=
        public interface Map<K, V> {

            V get(K key);
            void put(K key, V value);
            boolean contains(K key);
            K[] keys();
            V[] values();

        }
        ```
* For convention, we use letters like:
    * ``E``: element
    * ``T``: type
    * ``K``, ``V``: key and value
* Could you explain the following code snippet?
    ```java=
    public class Graph<N> extends Iterable<N> {

        List<List<N>> neighbors;
        public Graph(Set<N> nodes, Set<Tuple<N, N>> edges) { ... }

    }
    ```

## Upper Bound of Type Parameters
* We can put restrictions on the type parameters.
    ```java=
    interface List1<E extends Object> {
        ...
    }

    interface List2<E extends Number> {
        ...
    }

    public class UpperBoundGenericsDemo {

        public static void main(String[] args) {

            List1<Date> lst1 = ... // ok!
            List2<Date> lst2 = ... // compile-time error!

        }

    }
    ```
    * As you can see, you cannot use ``Date`` in ``List2<E extends Number>`` because ``Date`` is not a subtype of ``Number``.
    * So Java compiler can detect the error before you run the program.
    ==與其執行的時候才錯誤，不如寫程式的當下就知道有問題！==
* Let ``Type1`` and ``Type2`` (and so on) be any type. Then the syntax of **bounded** type parameters is as follws:
    ```java=
    class ClassName<T1 extends Tyep1, T2 extends Tyep2, ...> {}
    interface InterfaceName<T1 extends Tyep1, T2 extends Tyep2, ...> {}
    ```
* You can try this example: 
    ```java=
    public interface Path<N, P extends Path<N, P>> extends Iterable<N>, Comparable<Path<?, ?>> {

        public Iterator<N> iterator();
        ...

    }
    ```
* For multiple upper bounds on one type variable, you can use the operator & to cascade all types required. 
    ```java=
    class ClassName<T extends Class1 & Interface2 & Interface3 & ...> {}
    ```

## Generics & Subtyping
* Assume that ``Integer`` and ``Double`` are subtypes of ``Number``.
    ```java=
            Number number = new Integer(100);
            ...
            number = new Double(3.14);
    ```
* Now we consider to use these types in generics.
* We proceed to investigate the relation between generics and subtyping.
* Java subtyping is **invariant** with respect to generics: neither covariant nor contravariant.
    * Java adopts a conservative way.
    * For example, ``List<Integer>`` is not a subtype of ``List<Number>`` and vice versa.
* Rule:
    * Let ``X`` be any type.
    * If ``T1`` is not identical to ``T2``, then ``X<T1>`` is irrevalent with ``X<T2>``.
    ==簡而言之，<>內的型態不同時，就沒有繼承關係。==
* We can see the reasons below:
    * **Covariance** allows read-only operations. (Why?)
        ```java=
                List<Number> data = new List<Integer>();
                Number item = data.get(); // always ok
                data.add(5.28); // bazinga!!!
        ```

    * **Contravariance** allows write-only operations. (Why?)
        ```java=
                List<Integer> data = new List<Number>();
                Integer item = data.get(); // bazinga!!!
                data.add(0); // always ok
        ``` 
### More about the parameters
* We have seen ``List<Integer>`` and ``List<Number>`` are not subtype-related.
* But there is subtyping as expected on the generic types themselves.
* If ``HeftyBag`` extends ``Bag``, then 
    * ``HeftyBag<Integer>`` is a subtype of ``Bag<Integer>``;
    * ``HeftyBag<Number>`` is a subtype of ``Bag<Number>``;
    * ``HeftyBag<String>`` is a subtype of ``Bag<String>``.
    ==<>內形態相同時，holder本身的繼承關係是存在的。==
## Syntax of Generic Methods
* Why do we need generic methods?
    ```java=
    public class Util {

        public static void sum(List<Number> lst) { ... }

        public static void main(String[] args) {

            List<Integer> data = ...
            sum(data); // goes wrong in compile time

        }

    }
    ```

* As seen before, ``List<Integer>`` is not a subtype of ``List<Number>``.
* We can declare a new type parameter for the method.
    ```java=
    public class Util {

        public <T extends E> static void sum(List<T> lst) { ... }

        public static void main(String[] args) {

            List<Integer> data = ...
            sum(data); // pretty good!

        }

    }
    ```

* Check another example shown below.
    ```java=
    public class Util2 {

        public <T> static void copyTo(List<T> dst, List<T> src) { 
            for (T item: src)
                dst.add(item);
        }
        
       public static void main(String[] args) {
        
            List<Integer> src = Arrays.asList(10, 20, 30);
            List<Integer> dst = new ArrayList<>();
            Util.copyTo(dst, src);
        
        }

    }
    ```
    * What is the restriction of this solution?
        * You can only duplicate the data in the data structure of the same type.
        * For example, we can copy data from ``List<Integer>`` to ``List<Integer>``, but not from ``List<Integer>`` to ``List<Number>``.
* How about this example?
    ```java=
    public class Util2 {

        public <T1, T2 extends T1> static void copyTo(List<T1> dst, List<T2> src) { 
            for (T item: src)
                dst.add(item);
        }
        
        public static void main(String[] args) {
        
            List<Integer> src = Arrays.asList(10, 20, 30);
            List<Number> dst = new ArrayList<>();
            Util.copyTo(dst, src);
        
        }

    }
    ```

## Wildcard
* **P**roducer **E**xtends **C**onsumer **S**uper (**PECS**)
```java=
    public <T> static void copyTo(Collection<? super T> dst, Collection<? extends T> src) {
    
        for (T item: src)
            dst.add(item);
    
    }
```

## Comparison to Native Arrays
* Actually, the native array allows covariance.
* However, this leads to troubles which cannot be discovered in compile-time.
* For example, 
```java=
public class GenericsDemo2 {

	public static void main(String[] args) {
		
		Animal[] animals = new Dog[256]; // covariance
		add7(animals, new Cat());
		
	}
	
	public static void add7(Animal[] animals, Animal animal) {
		
		animals[7] = animal;
		
	}

}
```
* In this case, you encounter the **ArrayStoreException** at runtime.

## Restrictions on Java Generics
* Cannot instantiate generic types with primitive types.
    * Solution: you need those wrapper classes (``Integer``, ``Double``, ...).
* Cannot create instances of type parameters.
    * Solution: injection
* Cannot declare static fields whose types are type parameters.
    * Solution:
* Cannot use casts or instanceof With parameterized types.
* Cannot create arrays of parameterized types
    
* Cannot create, catch, or throw objects of parameterized types
* Cannot overload a method where the formal parameter types of each overload erase to the same raw type

## Application: Object Comparison
```java=
public class ComparisonDemo {

	public static void main(String[] args) {
		
		// TBD
		
	}

}
```