Author: Kilnn

Source: CSDN

The original link: blog.csdn.net/lonelyroame…

Basic concepts of generics

The definition of generics: Generics are a new feature in JDK 1.5. It is the application of Parameterized Type. This means that the data Type being operated on is specified as a parameter, and the specific Type is specified when it is used. This parameter type can be used in the creation of classes, interfaces, and methods, called generic classes, generic interfaces, and generic methods, respectively.

The idea of generics began to take root in the C++ language Templates. In the version of Java language without generics, type generalization could only be realized through the combination of Object being the parent class of all types and type casting. In hash table access, for example, the get() method of HashMap was used before JDK 1.5, and the return value is an Object Object. Since all types in the Java language inherit from java.lang.object, it is possible to convert an Object into any Object. But because of the infinite possibilities, only the programmer and the running virtual machine know what type of Object this Object is. At compile time, there is no way for the compiler to check whether an Object was successfully cast, and if the programmer is left to ensure that this operation is correct, much of the risk of ClassCastException is transferred to the program runtime.

Generics appear to be used in C# and Java in the same way, but there is a fundamental difference in implementation. In C# generics exist in program source code, in compiled IL (Intermediate Language, where generics are a placeholder), or in the runtime CLR. List and List are two different types that are generated during system runtime and have their own virtual method tables and type data. This implementation is called type inflation, and generics implemented based on this method are called true generics.

Generics in the Java language, on the other hand, exist only in the program source code. In the compiled bytecode file, they have been replaced with the original Raw Type (also known as Raw Type), and forced transformation code has been inserted in place. Therefore, for the Runtime Java language, ArrayList and ArrayList are the same class. So generics technology is actually a syntactic sugar of the Java language. The implementation method of generics in The Java language is called type erasures, and generics realized based on this method are called pseudo-generics. (Type erasure is learned later)

Code written using generics is more secure and readable than code that uses Object variables and then casts them. Generics are especially useful for collection classes.

Generic Programming means that you write code that can be reused by many different types of objects.

Case analysis:

Prior to JDK1.5, Java generic programming was implemented using inheritance. Because the Object class is the base class of the class you use, you only need to maintain a reference to type Object. ArrayList, for example, maintains only an array of Object references:

Public class ArrayList//JDK1.5 {public Object get(int I){...... } public void add(Object o){...... }... private Object[] elementData; }Copy the code

There are two problems with this:

  1. Without error checking, you can add objects of the class to the arraylist
  2. When fetching an element, a cast is required

In this way, it is easy to make mistakes, such as:

*/ ArrayList arrayList1=new ArrayList(); arrayList1.add(1); arrayList1.add(1L); arrayList1.add("asa"); int i=(Integer) arrayList1.get(1); // Type conversion is prone to errors because we do not know the type of the value retrievedCopy the code

The first element here is a long integer, and you thought it was an integer, so there was an error when it was strong.

So. After JDK1.5, generics were added to solve a similar problem. For example, using generics in ArrayList:

/ / ArrayList<String> arrayList2=new ArrayList<String>(); // arrayList2.add(1); // arraylist2.add (1L); / / for limits on the types, so can't add the whole long arrayList2. Add ("asa"); String STR =arrayList2.get(0); // Because you know the type of the fetched value, no casting is requiredCopy the code

Also understand that the generics feature is forward compatible. Although many of the classes in JDK 5.0’s standard library, such as the collection framework, have been genericized, existing code that uses collection classes, such as HashMap and ArrayList, continues to work in JDK 1.5 unchanged. Of course, existing code that does not take advantage of generics will not gain the type-safety benefits of generics.

Before we learn about generics, let’s take a look at some of the basic terms of generics, starting with ArrayList and ArrayList:

The whole thing becomes an ArrayList generic type

E in an ArrayList is called a type variable or type parameter

The entire ArrayList is called a parameterized type

An INTEGER in an ArrayList is called an instance of a type parameter or an actual type parameter

· Read typeof Integer in ArrayList

An ArrayList is called a primitive type

The use of generics

Generic parameter types can be used in the creation of classes, interfaces, and methods, called generic classes, generic interfaces, and generic methods, respectively. Let’s see how this is defined.

1. Definition and use of generic classes

A generic class is a class that has one or more type variables. Defining a generic class is as simple as adding a <> to the class name and a type parameter to it:

class Pair<T> {
	private T value;
        public Pair(T value) {
                this.value=value;
        }
        public T getValue() {
		return value;
	}
	public void setValue(T value) { this.value = value; }}Copy the code

Now we can use the generic class:

public static void main(String[] args) throws ClassNotFoundException {
		Pair<String> pair=new Pair<String>("Hello");
		String str=pair.getValue();
		System.out.println(str);
		pair.setValue("World");
		str=pair.getValue();
		System.out.println(str);
	}
Copy the code

The Pair class introduces a type variable T, enclosed in Angle brackets <> and placed after the class name. A generic class can have multiple type variables. For example, we could define the Pair class, where the first and second fields use different types:

public class Pair<T,U>{...... }Copy the code

Note: It is common for type variables to be capitalized and short. In the Java library, the variable E represents the element type of the collection, and K and V represent the type of the keyword and value, respectively. (use the adjacent letters U and S if necessary) for any type.

Definition and use of generic interfaces

Defining generic interfaces is similar to defining generic classes, as shown in the following simple example:

interface Show<T,U>{ void show(T t,U u); } class ShowTest implements Show<String,Date>{ @Override public void show(String str,Date date) { System.out.println(str); System.out.println(date); }}Copy the code

Test it out:

public static void main(String[] args) throws ClassNotFoundException {
		ShowTest showTest=new ShowTest();
		showTest.show("Hello",new Date());
	}
Copy the code

Definition and use of generic methods

Generic classes enforce type constraints across multiple method signatures. In the List, the type parameter V appears in the signature of the methods get(), add(), contains(), and so on. When you create a variable of type Map<K, V>, you declare a type constraint between methods. The value you pass to add() will be of the same type as the value returned by get().

Similarly, generic methods are declared generally because you want to declare a type constraint between multiple arguments to the method.

Here’s a simple example:

public static void main(String[] args) throws ClassNotFoundException {
		String str=get("Hello"."World");
		System.out.println(str);
	}
 
	public static <T, U> T get(T t, U u) {
		if(u ! = null)return t;
		else
			return null;
	}
Copy the code

Type qualification of generic variables

Above, we briefly studied generic classes, generic interfaces, and generic methods. We use this form directly to declare generic types.

There are times when classes, interfaces, or methods need to constrain type variables. Look at the following example:

There is a simple generic method:

public static <T> T get(T t1,T t2) {
        if(t1.compareTo(t2)>=0); // Error compilingreturn t1;
    }
Copy the code

Because before we compiled, when we were defining this generic method, we didn’t know what type T was, so we had to default to the primitive type Object. So it can only call the methods from Object, not the compareTo methods. But my intention is to compare T1 and T2, so what do I do? At this point, type qualification is used, setting a bound on the type variable T to do this.

We know that all methods that implement the Comparable interface will have compareTo methods. Therefore, the following restrictions can be made:

Public static <T extends Comparable> T get(T t1,T t2)if(t1.compareTo(t2)>=0);
		return t1;
	}
Copy the code

Type qualification can be used in generic classes, generic interfaces, and generic methods, with the following caveats:

  1. The extends keyword is used uniformly regardless of whether the qualification is a class or an interface

  2. You can use ampersand to give multiple qualifiers, such as

    public static <T extends Comparable&Serializable> T get(T t1,T t2)
Copy the code
  1. If the qualification has both an interface and a class, then there must be only one class and it must be placed first
public static <T extends Object&Comparable&Serializable> T get(T t1,T t2)
Copy the code

Android learning PDF+ architecture video + interview document + source notes

Next section: Architect Foundation Skills: Deep Java generics, wildcards, and nesting