Generics

1. Generic Type Erasing
Java will erase type during compile time, this is to provide backed compatibility.

The code:
void foo(List<Integer> integerList) {}
void foo(List<String> StringList) {}


will be seen as the same during compilation as they will remove the type. To the compiler it be seen as

void foo(List<Object> integerList) {}
void foo(List<Object> StringList) {}


which is the same method signature.




2. Java generics: Upper and lower bound wildCards _? extends upper_ _? super lower_

Let the generic be <? (extends/super) x) >
upper bound
For those that extend X
> Only retrieve
> no adding to the list
> can add null
List<? extends A> means a List of objects that are instances of class A, or subclasses of A (e.g. B and C).
When you know that the instances in the collection are of instances of A or subclasses of A, it is safe to read the instances of the collection and cast them to A instances.

Lower bound (super circle)
> add anything that is the class or the child
> cannot retrieve
> only object can be retrieved
List<? super A> means that the list is typed to either the A class, or a superclass of A.
When you know that the list is typed to either A or a superclass of A, it is safe to insert instances of A or subclasses of A (e.g. B or C) into the list.

3.  Type safety
Note: We cannot have a primitive type as a generic type. Meaning that we cannot have A<T> and assign T as int but we can use Integer which is the wrapper class for int
Failing to declare a type will result in a compiler warning due to type safety
e.g new A<>() or new A()
However, using the wrapper class will cause more memory to be used up and take longer compared to its primitive. This is due to the fact that the compiler needs to unbox the object.
Note:
Integer caching will allow numbers from -128 to 127 automatically auto box thus it will take a shorter time compared to 128. This is due to the caching of these numbers.

Generic cannot be used on static variables since the class can be used in a generic fashion and T can be anything. Thus we cannot keep changing the T

4. Generic Methods
Example of a generic method
public static <Type> Entry<Type, Type> twice(Type value) {
    return new Entry<Type, Type>(value, value);
}

The first <Type> represents the declaration of the symbol, removing it will throw a compilation error.
This is useful for static methods.
Previously, we are not able to create a generic static method, this will solve the problem for us.
For example:

public abstract class InfiniteListImpl<T> implements InfiniteList<T>{

protected abstract Optional<T> get();

    public <R> InfiniteList<R> map(Function<T,R> mapper){

        return new InfiniteListImpl<R>(){
            protected Optional<R> get(){
                return InfiniteListImpl.this.get().map(mapper);
            }
        };
 
    }




    public InfiniteList <T> limit(long maxSize){
 
       return new InfiniteListImpl<T>(){
     
           long fin = maxSize;
           protected Optional<T> get(){
           if(fin==0){
         
               return Optional.empty();
           }
           else{
         
               fin = fin-1;
               return InfiniteListImpl.this.get();
         
              }
           }
       };

   }
}


Based on the example code, the method map() has a generic <R>, however, this shows that the generic type is not referring to the class <T>.
It just declares a new type parameter <R>, scoped to the map method.
However <R> is only specific to this method only.
<R> in the method signature implies that the method will be dealing with generic type R.
Compared to the other method which is a method that belongs to a generic type, map() is a generic method because it defines its own parameter.

Edit: In the map method, the <R> is saying that Map return is returning an Object that is unrelated to Type <T> in the class generic.
- By classmate

Generic methods can be used when we notice the specific method has a reusable functionality. Thus we can make it a generic method.

5. Typecasting in Generic
Polymorphism does not exist in generic. Meaning if I have a <Object> o , we cannot Assign <Circle> c to it even thou Object is a super of Circle.
E.g Function < Object, Object> obo;
Function <Circle, Shape> CbS;
obo = CbS; //this will throw an error
CbS = obo; //this will also throw an error
We can only bypass this when we use wildcards that states the generic bounds that the object can be

<Prev Solid Principals                                                            Next Exception and Binding >

No comments:

Post a Comment