Of Java 泛型

First, the concept of generics

We often need to do more types of data for the same operation , but were prepared for each type and class method is very inefficient. For this purpose, the JDK. 5- introduced generics .
Generics provide type safety at compile time detection mechanism , this mechanism allows the programmer to detect an illegal type compile time .
Essence of generic parameters of the type , the type of data passed as parameters.
Type parameter must be a reference type type .

Second, generic

1. Generic Methods

Generic methods may be received when the calling parameters of different types , a predetermined different type of return value .
A generic method is defined as follows:

<类型参数声明>返回类型 方法名(形参表){
	//方法定义
}

The following is a simple example, and the generic method is called using two methods:

public class Demo {
	public static void main(String[] args) {
		Integer i = 123;
		Demo.<Integer>print(i);		//给定类型参数调用,该方法必须配合使用句点表示法,无法自动推断时使用
		print(i);					//Java8新增类型推断,一般采用该方法
	}
	
	public static <T> void print(T t) {
		System.out.println(t);
	}
}

If you want to type parameters within a particular range (usually the inheritance hierarchy range), you can use extends keyword. This keyword specifies the type argument must inherit a class or implements an interface .

//如没有extends,编译无法通过,因为不知道T是否定义了compareTo方法
public <T extends Comparable<T>> boolean smallerThan(T o1,T o2) {	
	if(o1.compareTo(o2) < 0)	
		return true;
	else
		return false;
}

Generic methods may also be used variable parameters , such as:

public <T> void print(T...args) {
	for(T t : args)
		System.out.println(t);
}

2. generic class

Generic class can be open to different types of data the same interface . The most typical is the variety of container classes.
A generic class is defined as follows:

class 类名<类型参数声明>{
	//实例/局部变量和实例方法可以使用类声明的类型参数
}

The following is a simple example and used in two ways:

class Test<T>{
	T value;
	public void set(T value) {
		this.value = value;
	}
	
	public T get() {
		return value;
	}
}

public class Demo {
	public static void main(String[] args) {
		//方法一:给定类型实参,实例对象只能接受给定类型的数据
		Test<Integer> test1 = new Test<Integer>();
		test1.set(6);
		//方法二:不给定类型实参,实例对象可以接受任何类型的数据
		Test test2 = new Test();
		test2.set(1);
		test2.set(2.0);
		test2.set("3");
	}
}

Generic method for each call will again push to re-type inference, therefore is safe . It should be used in the case of automatic inference.
Generic class instance Once initialized, its scope will persist within. Type parameter which is changed during unsafe , should be given by the arguments.

Generic Generic methods are
not generic class of methods are generic methods, such as:

class Test<T>{
	T value;
	public void set(T value) {	//不是一个泛型方法,只是使用了类声明的类型形参
		this.value = value;
	}
	
	public T get() {		//同上,不是一个泛型方法
		return value;
	}
	
	public <E> void print(E arg){		//这是一个泛型方法,他有单独的类型参数声明,这个方法中T和E均可使用
		System.out.print(arg.toString());
	}
	
	public <T> void println(T arg) {	//这也是一个泛型方法,但它将类给定的类型参数T隐藏(屏蔽)了,这里的T是自身的类型形参
		System.out.println(arg.toString());
	}
	//这两个方法主要是为了说明泛型类中的泛型方法,明确概念,两个函数本身不具应用意义
}

static methods and generic
static methods can not access instance member, and an example of one type parameter is a member, so that static methods can not use the type parameters class .
In the above example, add the following static class is not compile the method:

public static void print2(T arg){	//Error:不能对非静态类型T进行静态引用
	System.out.println(arg);
}

It gives a native type parameter is declared as static method, modified as follows:

public static <T> void print2(T arg) {
	System.out.println(arg);
}

3. Generic Interface

Generic interface defined and substantially the same generic class, often used in the production of various types, such as a comparator .

interface Print <T>{			//输出器
	public void print(T o);
}

When using the generic class implements an interface, the interface needs to pass a generic type parameter. Common transmission parameter to the generic class generic interface:

interface Print <T>{
	public void print(T o);
}

class Test<T> implements Print<T>{
	@Override
	public void print(T o) {
		System.out.println(o);
	}
}

4. Type Wildcard

When a generic class is instantiated with different types of parameters, it becomes different versions . Examples of different versions are not compatible , even if it is between a base class and subclasses.

public class Demo {
	public static void main(String[] args) {
		test(new Test<Base>());			//无错误
		test(new Test<Heir>());			//Error:方法 test(Test<Base>)对于参数(Test<Heir>)不适用
	}
	
	public static void test(Test<Base> arg) {	//规定仅接受Test<Base>版本,<>里必须给定类型,否则报错
		System.out.println(arg);
	}
}

class Base{}
class Heir extends Base{}
class Test<T>{}

To solve this problem, we use ? As the type of a wildcard , it can refer to all types. The above test method modified as follows, can be compiled.

//public static void test(Test<Base> arg)
public static void test(Test<?> arg) {
	System.out.println(arg);
}

The upper and lower boundaries of the generic

When using generics, we can accept the type parameter defines the upper and lower boundaries .
The provisions of the incoming type must be a type of a subclass / implement an interface ( upper bound ), or there must be some type of parent class ( lower bound ).
extends keyword to a predetermined upper bound, the upper bound may allow for a predetermined in Example member generic parent class, and allows polymorphic .

public class Demo {
	public static void main(String[] args) {
		test(new Test<Base>(new Base()));	//class learning_test.Base
		test(new Test<Heir>(new Heir()));	//class learning_test.Heir
	}
	
	public static void test(Test<? extends Base> arg) {
		arg.print();
	}
}

class Base{}
class Heir extends Base{}
class Test<T>{
	T value;
	public Test (T value) {
		this.value = value;
	}
	public void print() {
		System.out.println(value.getClass().toString());
	}
}

super keyword is used to specify a lower bound, i.e., receives only a given type of the parent class type . The above test of the parameter bits Test <? Super Heir>, main process will be given.

test(new Test<Base>(new Base()));	//无措
test(new Test<Heir>(new Heir()));	//Error:方法 test(Test<? super Base>)对于参数(Test<Heir>)不适用

When the test found, extends for any generic can be used, but can only be used with the type of super wildcard.

public static <T extends Base> void print1(T o){}	//无错误
public static <T super Base> void print2(T o){}		//Error:标记“super”上有语法错误,应为,
//第二行的错误报告看上去很奇怪,可能是将super识别为父类关键字super使用了
public static void print3(List<? extends Base> list) {}	//无错误
public static void print4(List<? super Base> list) {}	//无错误
Published 39 original articles · won praise 4 · Views 2035

Guess you like

Origin blog.csdn.net/weixin_44712386/article/details/105331356