枚举和泛型
枚举和泛型
本章目标
- 掌握枚举类型及使用
- 掌握泛型的特性
- 重点掌握泛型的使用
枚举的定义
枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常数
- 枚举在曰常生活中很常见,例如一个人的性别只能是“男”或者“女”,一周的星期只能是 7 天中的一个等。类似这种当一个变量有几种固定可能的取值时,就可以将它定义为枚举类型。
- •在 JDK 1.5 之前没有枚举类型,那时候一般用接口常量来替代。枚举类型是 JDK1.5 引入的新类型,在 Java 中它虽然算个“小”功能,却给我们开发带来了“大”方便
声明枚举
声明枚举时必须使用 enum 关键字,然后定义枚举的名称、可访问性、基础类型和成员等
枚举声明的语法如下:
enum-modifiers enum enumName {
enum-body,
}
- enum-modifiers 表示枚举的修饰符主要包括 public、private 和 internal
- enumname 表示声明的枚举名称
- enum-body 表示枚举的成员,它是枚举类型的命名常数
举例
//定义一个表示性别的枚举类型 SexEnum
public enum SexEnum {
MALE,FEMALE;
}
//定义一个表示颜色的枚举类型 ColorEnum
public enum ColorEnum {
RED,BLUE,GREEN,BLACK;
}
//使用枚举
ColorEnum color = ColorEnum.RED;
switch ( color ) {
case RED:
color = ColorEnum.GREEN;
break;
case YELLOW:
color = ColorEnum.RED;
break;
case GREEN:
color = ColorEnum.YELLOW;
break;
}
枚举类
Java 中的每一个枚举都继承自 java.lang.Enum 类。当定义一个枚举类型时,每一个枚举类型成员都可以看作是 Enum 类的实例,这些枚举成员默认都被 final、public, static 修饰,当使用枚举类型成员时,直接使用枚举名称调用成员即可。
所有枚举实例都可以调用 Enum 类的方法,常用方法如下:
- values():以数组形式返回枚举类型的所有成员
- valueOf():将普通字符串转换为枚举实例
- compareTo():比较两个枚举成员在定义时的顺序
- ordinal():获取枚举成员的索引位置
EnumMap类
EnumMap 是专门为枚举类型量身定做的 Map 实现。虽然使用其他的 Map(如 HashMap)实现也能完成枚举类型实例到值的映射,但是使用 EnumMap 会更加高效。
// 定义类型枚举
public enum DataBaseType {
MYSQUORACLE,DB2,SQLSERVER
}
// 创建 EnumMap实例
EnumMap<DataBaseType,String>urls = new EnumMap<DataBaseType,String>(DataBaseType.class);
urls.put(DataBaseType.DB2,"jdbc:db2://localhost:5000/sample"); urls.put(DataBaseType.MYSQL,"jdbc:mysql://localhost/mydb"); urls.put(DataBaseType.ORACLE,"jdbc:oracle:thin:@localhost:1521:sample"); urls.put(DataBaseType.SQLSERVER,"jdbc:microsoft:sqlserver://sql:1433;Database=mydb");
EnumSet 类
EnumSet 是枚举类型的高性能 Set 实现,它要求放入它的枚举常量必须属于同一枚举类型。EnumSet 提供了许多工厂方法以便于初始化
泛型
什么是泛型
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
- 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)
- 在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法
泛型的作用
List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);
for (int i = 0; i < arrayList.size(); i++) {
String value = (String)arrayList.get(i);
System.out.println(“item = " + item);
}
程序的运行结果会以崩溃结束
- ArrayList 可以存放任意类型,例子中添加了一个 String 类型,添加了一个Integer 类型,再使用时都以 String的方式使用,因此程序崩溃了
- 为了在编译阶段解决类似这样的问题,泛型应运而生
泛型的特性
泛型只在编译阶段有效
List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();
Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();
if (classStringArrayList.equals(classIntegerArrayList)){
System.out.println("类型相同");
}
泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型
- 编译之后程序会采取去泛型化的措施。也就是说 Java 中的泛型,只在编译阶段有效
- 在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段
泛型的使用
泛型类
泛型类型用于类的定义中,被称为泛型类,通过泛型可以完成对一组类的操作对外开放相同的接口(最典型的就是各种容器类,如:List、Set、Map)
public class className <T> {
private T variable;
...
}
}
泛型接口
泛型接口与泛型类的定义及使用基本相同,泛型接口常被用在各种类的生产器中
//定义一个泛型接口
public interface Generator<T> {
public T next();
}
//实现泛型接口
public class FruitGenerator implements Generator<String> {
private String[] fruits = new String[]{"Apple", "Banana", "Pear"};
@Override
public String next() {
Random rand = new Random();
return fruits[rand.nextInt(3)];
}
}
泛型通配符 ?
同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的
//类型通配符一般是使用?代替具体的类型实参
public void showKeyValue1(Genreic<?> obj) {
System.out.println("key value is " + obj.getKey());
}
- 可以解决当具体类型不确定的时候,可以使用通配符 ?
- 当操作类型时,不需要使用类型的具体功能时,只使用 Object 类中的功能,那么可以用 ? 通配符来表未知类型
泛型方法的定义
泛型类是在实例化类的时候指明泛型的具体类型,而泛型方法是在调用方法的时候指明泛型的具体类型
//定义泛型方法
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
IllegalAccessException{
T instance = tClass.newInstance();
return instance;
}
- public 与 返回值中间
非常重要,可以理解为声明此方法为泛型方法 - 只有声明了
的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法 表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T - 与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
泛型方法的应用
- 泛型方法与可变参数
public <T> void printMsg( T... args){
for(T t : args){
System.out.println("t is " + t);
}
}
可变参数的泛型方法与普通泛型方法本质上没有任何区别
- 静态方法与泛型
public class StaticGenerator<T> {
public static <T> void show(T t){
…
}
}
如果在类中定义使用泛型的静态方法,需要添加额外的泛型声明,即使静态方法要使用泛型类中已经声明过的泛型也不可以
总结
泛型在 Java 中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用
在实际的编程过程中,自己可以使用泛型去简化开发且能很好的保证代码质量