Java泛型02 : 泛型原始类型、泛型类型命名规范、有界类型

[超级通道:Java泛型学习系列-绪论]

本章主要对Java泛型类型的命名规范和有界泛型类型进行学习。

1.泛型相关概念

首先通过泛型类与泛型方法的语法,对几个概念进行说明:
泛型类与泛型方法示例

/**
 * 泛型类语法示例
 * Created by 韩超 on 2018/2/22.
 */
public class MyGenericsType<T> {
    private T t;

    /**
     * <p>Title: 这是一个普通方法</p>
     * @author 韩超 2018/2/22 10:52
     */
    public T getT() {
        return t;
    }

    /**
     * <p>Title: 这是一个泛型方法</p>
     * @author 韩超 2018/2/22 10:53
     */
    public <T> T getTT() {
        T t = null;
        return t;
    }
}

其中,

  • MyGenericsType:泛型类名,即泛型原始类型
  • <T>:泛型标识,标识这是一个泛型类或者泛型方法
  • T:泛型类型
  • t:泛型类型的实例对象

泛型原始类型可以独立使用,如下:
泛型原始类型

/**
 * <p>Title: 泛型原始类型使用</p>
 * @author 韩超 2018/2/22 11:21
 */
public static void main(String[] args){
    //泛型原始类型
    MyGenericsType myGenericsType = new MyGenericsType();
    LOGGER.info(myGenericsType.getClass().toString());

    //泛型类型
    MyGenericsType<Integer> integerMyGenericsType = new MyGenericsType<Integer>();
    LOGGER.info(integerMyGenericsType.getClass().toString());
}

运行结果:

2018-02-22 11:23:11 INFO  MyGenericsType:38 - class pers.hanchao.generics.type.MyGenericsType
2018-02-22 11:23:11 INFO  MyGenericsType:42 - class pers.hanchao.generics.type.MyGenericsType

发现泛型原始类型和泛型类型的实例化对象是一样的,这是由于类型擦除造成的,后续会进行讲解。

2.泛型类型命名规范

泛型类型的命名并不是必须为T,也可以使用其他字母,如XK等,只要是命名为单个大写字即可,例如:

/**
 * 泛型类语法示例
 * Created by 韩超 on 2018/2/22.
 */
class MyGenericsType2<X>{
    private X x;
}

虽然没有强制的命名规范,但是为了便于代码阅读,也形成了一些约定俗成的命名规范,如下:

  • T:通用泛型类型,通常作为第一个泛型类型
  • S:通用泛型类型,如果需要使用多个泛型类型,可以将S作为第二个泛型类型
  • U:通用泛型类型,如果需要使用多个泛型类型,可以将U作为第三个泛型类型
  • V:通用泛型类型,如果需要使用多个泛型类型,可以将V作为第四个泛型类型
  • E:集合元素 泛型类型,主要用于定义集合泛型类型
  • K:映射-键 泛型类型,主要用于定义映射泛型类型
  • V:映射-值 泛型类型,主要用于定义映射泛型类型
  • N:数值 泛型类型,主要用于定义数值类型的泛型类型

下面通过一些实例加深对这些类型的理解。

2.1.通用泛型类型:T,S,U,V…

通用泛型类型:适用于所有的泛型类型。

/**
 * <p>Title: 通用泛型类型示例</p>
 * @author 韩超 2018/2/22 11:09
 */
public class MyMultiType<T,S,U,V,A,B> {
    private T t;
    private S s;
    private U u;
    private V v;
    private A a;
    private B b;

    private final static Logger LOGGER = Logger.getLogger(MyMultiType.class);

    public void set(T first,S seconde,U third,V fourth,A fifth,B sixth){
        LOGGER.info("第1个参数的类型是:" + first.getClass().getName().toString());
        LOGGER.info("第2个参数的类型是:" + seconde.getClass().getName().toString());
        LOGGER.info("第3个参数的类型是:" + third.getClass().getName().toString());
        LOGGER.info("第4个参数的类型是:" + fourth.getClass().getName().toString());
        LOGGER.info("第5个参数的类型是:" + fifth.getClass().getName().toString());
        LOGGER.info("第6个参数的类型是:" + sixth.getClass().getName().toString());
    }

    /**
     * <p>Title: 测试通用泛型类型</p>
     * @author 韩超 2018/2/22 11:08
     */
    public static void main(String[] args){
        MyMultiType<Integer,Double,Float,String,Long,Short> myMultiType = new MyMultiType<Integer, Double, Float, String, Long, Short>();
        myMultiType.set(1,1D,1F,"1",1L, (short) 1);
    }
}

运行结果:

2018-02-22 11:09:27 INFO  MyMultiType:20 - 第1个参数的类型是:java.lang.Integer
2018-02-22 11:09:27 INFO  MyMultiType:21 - 第2个参数的类型是:java.lang.Double
2018-02-22 11:09:27 INFO  MyMultiType:22 - 第3个参数的类型是:java.lang.Float
2018-02-22 11:09:27 INFO  MyMultiType:23 - 第4个参数的类型是:java.lang.String
2018-02-22 11:09:27 INFO  MyMultiType:24 - 第5个参数的类型是:java.lang.Long
2018-02-22 11:09:27 INFO  MyMultiType:25 - 第6个参数的类型是:java.lang.Short

2.1.集合泛型类型:E

集合泛型类型:适用于泛型类型作为集合元素的泛型定义。

/**
 * <p>Title: 集合泛型类型示例</p>
 * @author 韩超 2018/2/22 11:11
 */
public class MyList<E> {
    private List<E> list = new ArrayList<E>();

    private final static Logger LOGGER = Logger.getLogger(MyList.class);

    public void myAdd(E e){
        list.add(e);
        LOGGER.info(e.toString());
    }

    public int mySize(){
        return list.size();
    }

    /**
     * <p>Title: 集合泛型类型示例</p>
     * @author 韩超 2018/2/22 11:11
     */
    public static void main(String[] args){
        MyList<String> stringMyList = new MyList<String>();
        stringMyList.myAdd(new String("hello!"));
    }
}

运行结果:

2018-02-22 11:10:59 INFO  MyList:23 - hello!

2.3.映射泛型类型:K,V

映射泛型类型:适用于泛型类型作为键值对的泛型定义。

/**
 * <p>Title: 映射泛型类型示例</p>
 * @author 韩超 2018/2/22 11:15
 */
public class MySet<K,V> {
    private Map<K,V> map = new HashMap<K, V>();

    private final static Logger LOGGER = Logger.getLogger(MySet.class);


    public void myPut(K key,V value){
        map.put(key,value);
        LOGGER.info("key:" + key.toString() + ",value=" + value.toString());
    }

    public int mySize(){
        return map.size();
    }
    /**
     * <p>Title: 映射泛型类型示例</p>
     * @author 韩超 2018/2/22 11:14
     */
    public static void main(String[] args){
        MySet<String,Integer> mySet = new MySet<String, Integer>();
        mySet.myPut("001",100);
    }
}

运行结果:

2018-02-22 11:15:23 INFO  MySet:20 - key:001,value=100
2.4.数值泛型类型

映射泛型类型:适用于泛型类型作为键值对的泛型定义。

/**
 * <p>Title: 数值泛型类型示例</p>
 * @author 韩超 2018/2/22 11:16
 */
public class MySquare<N> {
    private final static Logger LOGGER = Logger.getLogger(MySquare.class);

    public void square(N number){
        LOGGER.info(number.getClass().toString() + ":" + number);
    }

    /**
     * <p>Title: 数值泛型类型示例</p>
     * @author 韩超 2018/2/22 11:16
     */
    public static void main(String[] args){
        MySquare<Integer> mySquare = new MySquare<Integer>();
        mySquare.square(1);
    }
}

运行结果:

2018-02-22 11:19:07 INFO  MySquare:13 - class java.lang.Integer:1

3.有界泛型类型

如果不对泛型类型做限制,则泛型类型可以实例化成任意类型,这种情况可能产生某些安全性隐患。
为了限制允许实例化的泛型类型,我们需要一种能够限制泛型类型的手段,即:有界泛型类型
要实现有界泛型类型,只需要在泛型类型后面追加extends 父类型即可,语法如下:

//有界泛型类型语法 - 继承自某父类
<T extends ClassA>
//有界泛型类型语法 - 实现某接口
<T extends InterfaceB>
//有界泛型类型语法 - 多重边界
<T extends ClassA & InterfaceB & InterfaceC ... >

//示例
<N extends Number> //N标识一个泛型类型,其类型只能是Number抽象类的子类
<T extends Number & Comparable & Map> //T标识一个泛型类型,其类型只能是Person类型的子类,并且实现了Comparable 和Map接口

其中,

  • T:泛型类型
  • extends:边界关键字,可以标识extends ClassA,也可以标识implements InterfaceB
  • &:多重边界,与类的继承机制类似:可以实现一个父类和实现多个接口。
  • ClassA :父类:必须在第一位。

下面通过程序示例加深理解。

/**
 * 有界类型参数
 * Created by 韩超 on 2018/1/30.
 */
public class MyMath {

    private final static Logger LOGGER = Logger.getLogger(MyMath.class);

    /**
     * <p>Title: 有界参数类型(单重)</p>
     * @author 韩超 2018/1/31 10:37
     */
    public static <T extends Comparable> T MyMax(T x, T y) {
        T max = x;
        if (y.compareTo(max) > 0) {
            max = y;
        }
        return max;
    }

    /**
     * <p>Title: 多重有界参数类型</p>
     * @author 韩超 2018/1/31 13:20
     */
    public static <T extends Number & Comparable> T MyMax2(T x, T y){
        T dmax = x.doubleValue() >= y.doubleValue() ? x : y;
        return dmax;
    }

    /**
     * <p>Title: 有界泛型类型示例</p>
     * @author 韩超 2018/2/22 11:44
     */
    public static void main(String[] args){
        Integer result = MyMath.MyMax(1,2);
        LOGGER.info(result);

        Double result1 = MyMath.MyMax2(1D,2D);
        LOGGER.info(result1);
    }
}

运行结果:

2018-02-22 11:45:06 INFO  MyMath:42 - 2
2018-02-22 11:45:06 INFO  MyMath:45 - 2.0

使用有界泛型类型有两个好处:

  1. 在一定程度上限制泛型类型,提高程序安全性
  2. 因为定义了边界,所以可以调用父类或父接口的方法,如y.doubleValue()。这种情况比单纯的调用Object类提供的方法更加灵活。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值