Java泛型详解

引言

Java的泛型(generics)是JDK5中引入的一个新特性,它提供了编译时类型安全的检测机制,该机制允许在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。下面我们分为四个部分进行讲解

泛型方法的规则:
1):泛型方法声明时候会有一个类型参数声明部分,是由尖括号<>进行分隔的,在方法的返回值类型之前。
2):每一个类型参数声明部分包含一个或者多个类型参数,参数间用逗号分隔,一个泛型参数也被称作一个类型变量,是用于指定一个泛型类型名称的标识符。
3):类型参数能够被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
4):泛型方法体的声明和其他方法一样,注意类型参数只能代表引用型类型,不能是原始类型。

  • 泛型方法
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();
    }
}

这里写图片描述

  • 有界的类型参数
    有时候我们传递参数的时候会对参数范围做一些限制,比如我只想传递某一个类或者他的子类,并不是所有的类都可以作为泛型的参数传进去,这时候就会使用到有界的类型参数;比如这里我自定义的一个适配器类,其中E就只能传递TemplateViewHolder或者它的子类才可以,否则会报错。

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();

}
  • 泛型类
    在实际的开发中,泛型类非常实用,比如我们将通过接口返回的数据的模板固定,那么我们只需要将真正的数据使用泛型来传递即可,例子如下:
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());
    }
}

结果是:
这里写图片描述

  • 类型通配符
    1 类型通配符一般是使用?来代替的,可以传入任意类型的参数,和泛型E的区别就是不需要在返回值类型前面加上尖括号<>
    2 类型通配符还可以使用
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));
    }
}

这里写图片描述

好了,泛型的讲解就到这里了

猜你喜欢

转载自blog.csdn.net/oman001/article/details/79052918