Java - Generics

Keywords: Java

The concept of generics was introduced in JDK5. The purpose is to improve the robustness of the program, which may cause errors at run time to be exposed at compile time. For example, we often encounter errors: ClassCastException.

Defining generics, when insightful, is also simple. But it's good to have a more proficient level of proficiency in reading the source code.

What you need to pay attention to when using generics:

  • Instance class sharing

When the program runs, generic classes are shared by all instances of such classes. Because in fact, generics are erased in compiled bytecode classes. For example, ArrayList and ArrayList types. They share a Class instance of the same ArrayList class at runtime.

ArrayList<String> str = new ArrayList<String>();
ArrayList<Integer> integer = new ArrayList<Integer>();

//The answer is true.
System.out.println("str.getClass and integer.getClass Is it equal?"+(str.getClass() == integer.getClass()));
  • Illegal method overload

The compiler does not allow two methods with the same name to be defined in a class, with the same type of class as the parameter, otherwise the compiler will report errors.

  • instanceof error operation

The instanceof operation cannot be used for exact generics, otherwise compilation errors will occur.

  • Mandatory Type Conversion of Generics

Generic types cannot be used for mandatory type conversion, otherwise there are security risks. A ClassCastException exception occurs at runtime with the following inexpensive warnings

public static void main(String[] args) {
        Collection collection = new ArrayList<String>();
        collection.add("hello");

        ArrayList<Integer> integers = (ArrayList<Integer>) collection;
        integers.add(666);
        for (Integer integer : integers) {
            System.out.println(integer);
        }
    }

Operation results:

Generics of Java Collections

List<String> list = new ArrayList<String>();

The code declares that only type elements String can be stored in the List table, if other types of elements are added to the table again. For example, list.add(8); type incompatibility errors occur during compilation, which can be detected in time.

Generic classes, generic interfaces, and generic arrays

By adding generics to a class, it is similar to abstracting the type. Because through the generics of classes, we can achieve specific things.

Use the'extends'keyword to qualify type parameters; use the wildcard character'?' to refer to any data type;

public class JavaTest<K extends Integer, V, T>{
    private Map map = new HashMap<K, V>();
    private T[] t;


    public static void main(String[] args) {
        JavaTest java1 = new JavaTest<Integer, String, String>();   
        java1.putMap(1, "hello");
        java1.putMap(2, "world");
        System.out.println(java1.getMap().get(1));

        Integer[] ints = new Integer[] {666, 518};
        JavaTest java2 = new JavaTest<Integer, String, Integer>();
        java2.setArray(ints);
        for (Integer integer : ints) {
            System.out.println(integer);
        }

    }


    public void putMap(K k, V v) {
        map.put(k, v);
    }

    public Map<K, V> getMap() {
        return this.map;
    }


    public void setArray(T[] t) {
        this.t = t;
    }

    public T[] getArray() {
        return this.t;
    }

}

generic method

In a method, the type of parameter or return value has a type parameter in the form of <T>, so this method becomes a generic method.

public class Dollar{

    //generic method printArray
    public static <E> void printArray(E[] args) {
        for (int i = 0; i < args.length; i++) {
            System.out.println("Print Array Content->>>"+args[i]);
        }
    }

    //generic method printMax
    public static <T extends Comparable<T>> T printMax(T x, T y) {

        return x.compareTo(y) > 0 ? x : y;
    }

    public static void main(String[] args) {
        Integer[] ints = {518, 666, 668};
        printArray(ints);

        System.out.println(printMax(ints[1], ints[0]));
    }
}

Generics allow you to declare type parameters (such as <T>) when defining classes or methods, and provide explicit type parameters when programs access classes or playback.
The main two functions of generics are: compiler can check whether various assignment operations are type compatible according to generic parameters when compiling. This avoids ClassCastException runtime exceptions; simplifies program code and eliminates the need for mandatory type conversions.

Posted by Xil3 on Wed, 15 May 2019 02:03:20 -0700