[超级通道:Java泛型学习系列-绪论]
本章主要对Java泛型类型的命名规范和有界泛型类型进行学习。
首先通过泛型类与泛型方法的语法,对几个概念进行说明:
泛型类与泛型方法示例
/**
* 泛型类语法示例
* Created by 韩超 on 2018/2/22.
*/
public class MyGenericsType<T> {
private T t;
/**
* Title: 这是一个普通方法
* @author 韩超 2018/2/22 10:52
*/
public T getT() {
return t;
}
/**
* Title: 这是一个泛型方法
* @author 韩超 2018/2/22 10:53
*/
public T getTT() {
T t = null;
return t;
}
}
其中,
MyGenericsType
:泛型类名,即泛型原始类型
:泛型标识,标识这是一个泛型类或者泛型方法T
:泛型类型t
:泛型类型的实例对象泛型原始类型可以独立使用,如下:
泛型原始类型
/**
* Title: 泛型原始类型使用
* @author 韩超 2018/2/22 11:21
*/
public static void main(String[] args){
//泛型原始类型
MyGenericsType myGenericsType = new MyGenericsType();
LOGGER.info(myGenericsType.getClass().toString());
//泛型类型
MyGenericsType integerMyGenericsType = new MyGenericsType();
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
发现泛型原始类型和泛型类型的实例化对象是一样的,这是由于类型擦除造成的,后续会进行讲解。
泛型类型的命名并不是必须为T
,也可以使用其他字母,如X
、K
等,只要是命名为单个大写字即可,例如:
/**
* 泛型类语法示例
* Created by 韩超 on 2018/2/22.
*/
class MyGenericsType2{
private X x;
}
虽然没有强制的命名规范,但是为了便于代码阅读,也形成了一些约定俗成的命名规范,如下:
下面通过一些实例加深对这些类型的理解。
通用泛型类型:适用于所有的泛型类型。
/**
* Title: 通用泛型类型示例
* @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());
}
/**
* Title: 测试通用泛型类型
* @author 韩超 2018/2/22 11:08
*/
public static void main(String[] args){
MyMultiType myMultiType = new MyMultiType();
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
集合泛型类型:适用于泛型类型作为集合元素的泛型定义。
/**
* Title: 集合泛型类型示例
* @author 韩超 2018/2/22 11:11
*/
public class MyList<E> {
private List list = new ArrayList();
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();
}
/**
* Title: 集合泛型类型示例
* @author 韩超 2018/2/22 11:11
*/
public static void main(String[] args){
MyList stringMyList = new MyList();
stringMyList.myAdd(new String("hello!"));
}
}
运行结果:
2018-02-22 11:10:59 INFO MyList:23 - hello!
映射泛型类型:适用于泛型类型作为键值对的泛型定义。
/**
* Title: 映射泛型类型示例
* @author 韩超 2018/2/22 11:15
*/
public class MySet<K,V> {
private Map map = new HashMap();
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();
}
/**
* Title: 映射泛型类型示例
* @author 韩超 2018/2/22 11:14
*/
public static void main(String[] args){
MySet mySet = new MySet();
mySet.myPut("001",100);
}
}
运行结果:
2018-02-22 11:15:23 INFO MySet:20 - key:001,value=100
映射泛型类型:适用于泛型类型作为键值对的泛型定义。
/**
* Title: 数值泛型类型示例
* @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);
}
/**
* Title: 数值泛型类型示例
* @author 韩超 2018/2/22 11:16
*/
public static void main(String[] args){
MySquare mySquare = new MySquare();
mySquare.square(1);
}
}
运行结果:
2018-02-22 11:19:07 INFO MySquare:13 - class java.lang.Integer:1
如果不对泛型类型做限制,则泛型类型可以实例化成任意类型,这种情况可能产生某些安全性隐患。
为了限制允许实例化的泛型类型,我们需要一种能够限制泛型类型的手段,即:有界泛型类型
要实现有界泛型类型,只需要在泛型类型后面追加extends 父类型即可,语法如下:
//有界泛型类型语法 - 继承自某父类
//有界泛型类型语法 - 实现某接口
//有界泛型类型语法 - 多重边界
//示例
//N标识一个泛型类型,其类型只能是Number抽象类的子类
//T标识一个泛型类型,其类型只能是Person类型的子类,并且实现了Comparable 和Map接口
其中,
下面通过程序示例加深理解。
/**
* 有界类型参数
* Created by 韩超 on 2018/1/30.
*/
public class MyMath {
private final static Logger LOGGER = Logger.getLogger(MyMath.class);
/**
* Title: 有界参数类型(单重)
* @author 韩超 2018/1/31 10:37
*/
public static T MyMax(T x, T y) {
T max = x;
if (y.compareTo(max) > 0) {
max = y;
}
return max;
}
/**
* Title: 多重有界参数类型
* @author 韩超 2018/1/31 13:20
*/
public static T MyMax2(T x, T y){
T dmax = x.doubleValue() >= y.doubleValue() ? x : y;
return dmax;
}
/**
* Title: 有界泛型类型示例
* @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
使用有界泛型类型有两个好处:
y.doubleValue()
。这种情况比单纯的调用Object类
提供的方法更加灵活。