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) {} //无错误