When Android talks about generics, everyone is very Buddhist, [Daniel crazy teaching]

 public void startTest() {

        Tested<Test1th> test = new Tested<>();

        test.set(new Test1th());

        Test1th td = test.get();

    } 

Very simple. What if we need Tested to hold multiple objects? Look at chestnuts:

public class Tested<A, B> {

    private A a;

    private B b;



    public void set(A a, B b) {

        this.a = a;

        this.b = b;

    }



    public A getA() {

        return a;

    }



    public B getB() {

        return b;

    }

} 

New test class Test2th:

public class Test2th { } 

When used, specify the type for a and B. Of course, tested < A, b > also supports inheritance, which can be extended through test2ed < A, B, C > extend tested < A, b >.

 public void startTest() {

        Tested<Test1th, Test2th> test = new Tested<>();

        test.set(new Test1th(), new Test2th());

        Test1th tdA = test.getA();

        Test2th tdB = test.getB();

    } 

[](

)Generic interface

Generics can also be applied to interfaces. Generic interfaces are the same as generic classes in use. Here, take the common generic interface Iterable < T > as an example to make tested < A, b > have simple iteration function. Note that when using a generic interface, you should specify the generic parameter type of the generic interface. TestBase is shown below:

public class TestBase { } 

Chestnut tested < A, b > see below. Maybe you also noticed iterator < testbase >, which shows that generics can also be applied to anonymous inner classes.

public class Tested<A, B> implements Iterable<TestBase> {

    private A a;

    private B b;



    public Tested(A a, B b) {

        this.a = a;

        this.b = b;

    }



    @Override

    public Iterator<TestBase> iterator() {

        return new Iterator<TestBase>() {

            @Override

            public boolean hasNext() {

                return a != null || b != null;

            }



            @Override

            public TestBase next() {

                TestBase tb = null;

                if (a instanceof TestBase) {

                    tb = (TestBase) a;

                    a = null;

                } else if (b instanceof TestBase) {

                    tb = (TestBase) b;

                    b = null;

                }

                return tb;

            }

        };

    }

} 

Now there is a test class Test1th:

public class Test1th extends TestBase {

    @Override

    public String toString() {

        return getClass().getSimpleName();

    }

} 

There is also test class Test2th:

public class Test2th extends TestBase {

    @Override

    public String toString() {

        return getClass().getSimpleName();

    }

} 

When using, we can specify the generic parameter type for the generic class Tested. The iteration is as follows:

 public void startTest() {

        Tested<Test1th, Test2th> ts = new Tested<>(new Test1th(), new Test2th());

        for (TestBase t : ts) {

            String str = t.toString();

        }

    } 

[](

)Generic method

Whether or not you have generic methods has nothing to do with whether or not the class you are in is a generic class. To put it bluntly, generic methods can be independent of classes, and generic methods can express their intentions more clearly.

In addition, because static methods cannot access the generic parameters of generic classes, if static methods want to have generic capabilities, they must become generic methods.

For example, when using a generic class, the generic parameter list is placed in angle brackets after the class, and when using a generic method, the generic parameter list is placed before the return value (the list can support multiple), as follows:

public class Tested {

    public <T> void startTest(T t) { }

} 

Generic methods can also be used with variable parameters. Take a look at the asList method at the bottom of Arrays.

 public static <T> List<T> asList(T... a) {

        return new ArrayList<>(a);

    } 

If you don't understand, in Tested, do you understand in another way:

public class Tested {



    /**

     * Generic methods with variable parameters

     */

    public <T> List<T> asList(T... a) {

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

        for (T t : a)

            list.add(t);

        return list;

    }

} 

[](

)Erasure and boundary

When it comes to generics, it is inevitable to talk about erasure and boundary, which is also well understood. Before we say erase, let's take a look at this code and output the result?

public class Tested {



    public boolean startTest() {

        Class c1 = new ArrayList<String>().getClass();

        Class c2 = new ArrayList<Integer>().getClass();

        return c1 == c2;

    }

} 

The result is true. Why? Because JAVA generics are implemented using erasure. Inside the generic code, we can't get any information about the generic parameter types. Any specific type information is erased. The only thing we know is that we are using an object.

Therefore, List < string > and List < integer > are actually the same type at runtime, and both forms are erased into their "native" type, that is, List.

Look at the following code Tested. Since T does not specify the specific type, writing t.test() in this way can not pass the compilation:

public class Tested<T> {

    private T t;



    public void set(T t) {

        this.t = t;

    }



    public T get() {

        return t;

    }



    public void sT() {

        t.test(); // err: unable to compile

    }

} 

Existing test class TestBase:

public class TestBase {

    public void test() { }

} 

In order to call the test method, we must assist the generic class and give the boundary of the generic class, so as to tell the compiler that only types that follow this boundary can be accepted. Here, use the extend keyword to set the boundary. Let's look at the following code:

public class Tested<T extends TestBase> {

    private T t;



    public void set(T t) {

        this.t = t;

    }



    public T get() {

        return t;

    }



    public void sT() {

        t.test(); // suc: compilation succeeded

    }

} 

The boundary < T extends TestBase > declares that t must have TestBase type or its subtype, so that the test method can be called.

The type parameter of the generic type will be erased to its first boundary, that is, our compiler will replace the type parameter with its erase boundary class. As in the above example, T is erased to TestBase, just as T is replaced with TestBase in the class declaration.

Generic types only appear during type checking, after which all generic types in the program will be erased and replaced with their non Generic upper bounds.

For example, List < T > will be erased as List, while ordinary type variable t will be erased as Object. Because erasure removes type information, methods called with unbounded generic parameters are only those that can be called with Object.

If t does not specify a type, t cannot be used to explicitly reference the operation of runtime type, so new T(), obj instance T, (T) obj are all wrong. For example, chestnuts:

public class Tested<T> {

    private T t;



    public void set(T t) {

        this.t = t;

        new T(); // Unable to compile

    }



    public T get() {

        return t;

    }

} 

Although T will be erased as an Object, we can still assign a specific type of Object e to this Object t Object, and then strongly convert t to type E. refer to the following chestnuts:

 public void startTest() {

        Tested<String> td = new Tested<>();

        td.set("test");

        String obj = td.get();

    } 

You may wonder why String obj = td.get(), since Tested erases generic T into Object at compile time after type checking;

Can I get a String Object directly instead of an Object object Object? In fact, the compiler helps us automatically insert the transformed code into the Class file, which is no different from the following code, because the compiled Class file is the same.

public class Tested {

    private Object t;



    public void set(Object t) {

        this.t = t;

    }



    public Object get() {

        return t;

    }

} 

public void startTest() {

    Tested td = new Tested();

    td.set("test");

    String obj = (String) td.get();

} 


Said so much, then why JAVA What about erasure? It is mainly a compatibility problem, how to ensure that class libraries with low versions or without generics can be used normally.



for example A Generics are used, but A Class libraries used B No generics, what should I do? This requires that in the actual "communication", the A Generic information erasure to ensure that the class libraries of "communication" are consistent.



### [](

)Erase compensation





Finally, if you have any good learning methods or suggestions, you are welcome to leave a message in the comments. I hope you can learn, work together and make progress together.

**[CodeChina Open source project address: Android study PDF+Architecture video+Interview documents+Source notes](

)**

**Xiaobian wishes all the friends can be promoted and raised in the future, become the general manager and take the post of director CEO,Marry Bai Fumei and go to the peak of life!!**

> No matter what difficulties we encounter, they should not be the reason for us to give up!

Many people always encounter some problems when they first contact this industry or encounter a bottleneck period. For example, after learning for a period of time, they feel they have no sense of direction and don't know where to start to learn

If you see here and think the article is well written, give it a praise? If you think there is something worth improving, please leave me a message and will seriously query and correct the deficiencies. Thank you.



> **This article has been[tencent CODING Open source hosting project:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://ali1024.coding.net/public/P7/Android/git), self-study resources and series of articles are constantly updated**

Keywords: Java Android Design Pattern Programmer

Added by davidwhiteuk on Sun, 21 Nov 2021 04:11:17 +0200