Java泛型02 : 泛型原始类型、泛型类型命名规范、有界类型
2018-02-22 11:56
295 查看
[超级通道:Java泛型学习系列-绪论]
本章主要对Java泛型类型的命名规范和有界泛型类型进行学习。
泛型类与泛型方法示例
其中,
泛型原始类型可以独立使用,如下:
泛型原始类型
运行结果:
发现泛型原始类型和泛型类型的实例化对象是一样的,这是由于类型擦除造成的,后续会进行讲解。
虽然没有强制的命名规范,但是为了便于代码阅读,也形成了一些约定俗成的命名规范,如下:
T:通用泛型类型,通常作为第一个泛型类型
S:通用泛型类型,如果需要使用多个泛型类型,可以将S作为第二个泛型类型
U:通用泛型类型,如果需要使用多个泛型类型,可以将U作为第三个泛型类型
V:通用泛型类型,如果需要使用多个泛型类型,可以将V作为第四个泛型类型
E:集合元素 泛型类型,主要用于定义集合泛型类型
K:映射-键 泛型类型,主要用于定义映射泛型类型
V:映射-值 泛型类型,主要用于定义映射泛型类型
N:数值 泛型类型,主要用于定义数值类型的泛型类型
下面通过一些实例加深对这些类型的理解。
运行结果:
运行结果:
运行结果:
运行结果:
为了限制允许实例化的泛型类型,我们需要一种能够限制泛型类型的手段,即:有界泛型类型
要实现有界泛型类型,只需要在泛型类型后面追加extends 父类型即可,语法如下:
其中,
T:泛型类型
extends:边界关键字,可以标识extends ClassA,也可以标识implements InterfaceB。
&:多重边界,与类的继承机制类似:可以实现一个父类和实现多个接口。
ClassA :父类:必须在第一位。
下面通过程序示例加深理解。
运行结果:
使用有界泛型类型有两个好处:
在一定程度上限制泛型类型,提高程序安全性
因为定义了边界,所以可以调用父类或父接口的方法,如
本章主要对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,也可以使用其他字母,如
X、
K等,只要是命名为单个大写字即可,例如:
/** * 泛型类语法示例 * 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
使用有界泛型类型有两个好处:
在一定程度上限制泛型类型,提高程序安全性
因为定义了边界,所以可以调用父类或父接口的方法,如
y.doubleValue()。这种情况比单纯的调用
Object类提供的方法更加灵活。
相关文章推荐
- JS基础篇:数据类型&变量命名规范
- js基础:数据类型,变量命名规范
- js基础:数据类型,变量命名规范
- 02--java中---注释、标识符、命名规范、数据类型
- C#数据类型、控件、数据类型、ADO.NET等命名规范
- paip.使用泛型时未能找到类型或命名空间名称“T
- c语言基础数据类型及命名规范
- 3.1java数据类型-注释-命名规范-简介
- .NET 命名规范(控件、数据类型等)
- js基础:数据类型,变量命名规范、
- C#命名规范,控件、数据类型、ADO.NET等
- C#数据类型、控件、数据类型、ADO.NET等命名规范
- javascript数据类型和变量命名规范
- JavaScript发展史,与JScript区别,引入方式,数据类型,命名规范,命名推荐,解决命名冲突
- js变量命名规范与变量类型
- 【JavaSE系列-基础篇6】——泛型原始类型
- C#命名规范,控件、数据类型、ADO.NET等
- JAVA中变量的类型及命名规范
- JavaScript发展史,与JScript差别,引入方式,数据类型,命名规范,命名推荐,解决命名冲突
- python 变量命名规范及变量类型总结