introduction
Java's generics (generics) is a new feature introduced in JDK5, which provides a compile-time type safety detection mechanism, which allows illegal types to be detected at compile time. The essence of generics is that they are parameterized types, that is, the data type being manipulated is specified as a parameter. Below we divide it into four parts to explain
Rules for generic methods:
1): When a generic method is declared, there will be a type parameter declaration part, which is separated by angle brackets <>, before the return value type of the method.
2): Each type parameter declaration part contains one or more type parameters, which are separated by commas. A generic parameter is also called a type variable, which is an identifier used to specify a generic type name.
3): Type parameters can be used to declare the return value type and can be used as placeholders for the actual parameter types obtained by the generic method.
4): The declaration of the generic method body is the same as that of other methods. Note that the type parameter can only represent a reference type, not a primitive type.
- generic method
public class PrintArray {
public static void main(String[] args) {
Integer[] integers = {1, 2, 3};
String[] strings = {"Hello", "World"};
printArray(integers);
printArray(strings);
}
/**
* 泛型打印数组
*
* @param array
* @param <T>
*/
public static <T> void printArray(T[] array) {
for (T t : array) {
System.out.print(" "+t);
}
System.out.println();
}
}
- Bounded type parameters
Sometimes when we pass parameters, we limit the parameter range. For example, I only want to pass a certain class or its subclasses. Not all classes can be passed in as generic parameters. This Sometimes bounded type parameters will be used; for example, here is an adapter class I customized, in which E can only pass TemplateViewHolder or its subclasses, otherwise an error will be reported.
public abstract class TemplateListAdapter<T, E extends TemplateViewHolder> extends BaseAdapter {
public Context mContext;
public List<T> mData;
public LayoutInflater mInflater;
public TemplateListAdapter(Context context, List<T> data) {
mInflater = LayoutInflater.from(context);
mContext = context;
mData = data;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
E holder;
if (convertView == null) {
convertView = mInflater.inflate(getLayoutID(), null);
holder = getViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (E) convertView.getTag();
}
bindData(position, holder);
return convertView;
}
protected abstract void bindData(int position, E holder);
protected abstract E getViewHolder(View convertView);
protected abstract int getLayoutID();
}
- Generic classes
In actual development, generic classes are very useful. For example, if we fix the template of the data returned through the interface, then we only need to use generics to pass the real data. Examples are as follows:
class Result<T> {
private T data;
private int code;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public static void main(String[] args) {
Result<String> stringResult = new Result<>();
stringResult.setData("Hello World");
System.out.println("String:"+stringResult.getData());
Result<Integer> intResult = new Result<>();
intResult.setData(123456789);
System.out.println("Integer:"+intResult.getData());
}
}
turn out:
- Type wildcard
1 Type wildcard is generally replaced by ?, you can pass in any type of parameter, the difference from generic E is that you do not need to add angle brackets <> before the return value type
2 Type wildcard can also be used
public class PrintArray {
public static void main(String[] args) {
Integer[] integers = {1, 2, 3};
String[] strings = {"Hello", "World"};
printArray(integers);
printArray(strings);
List<String> list = new ArrayList<>();
list.add("hello");
printArray(list);
List<Integer> list1 = new ArrayList<>();
list1.add(23);
printArray2(list1);
List<Number> list2 = new ArrayList<>();
list2.add(2.5);
printArray3(list2);
}
/**
* 泛型打印数组
*
* @param array
* @param <T>
*/
public static <T> void printArray(T[] array) {
for (T t : array) {
System.out.print(" " + t);
}
System.out.println();
}
/**
* 泛型打印集合
*
* @param data
* @param <E>
*/
public static <E> void printArray(List<E> data) {
System.out.println("泛型:"+data.get(0));
}
/**
* 类型通配符打印数据
* @param data
*/
public static void printArray2(List<?> data) {
System.out.println("类型通配符?:"+data.get(0));
}
public static void printArray3(List<? extends Number> data) {
System.out.println("类型通配符extends:"+data.get(0));
}
}