1. JDK5 枚举
用一个全新的关键字enum来定义一个枚举类。下面就是一个典型枚举类型的定义:public enum Color {
RED, BLUE, BLACK;
}
用普通的类来模拟java中的枚举类型:
public class Color {
// Step1. 私有化构造方法
private Color() {
}
// Step2. 每一个元素为全局常量,public static final ----枚举中的常量元素
public static final Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color BLACK = new Color();
}
(1)、Color枚举类是一个特殊的class,而且是一个不可以被继承的final类。其枚举值(RED,BLUE...)都是Color类型的类静态常量, 我们可以通过下面的方式来得到Color枚举类的一个实例:Color c=Color.RED;
注意:这些枚举值都是public static final的,也就是我们经常所定义的常量方式,因此枚举类中的枚举值最好全部大写。
枚举关键字enum的好处:
[1].省略public static final的书写形式
[2]. 省略私有化构造函数
简单的枚举应用:
public enum Color {
RED, BLUE, BLACK;
public static void main(String[] args) {
// 获得枚举实例序号
int index = RED.ordinal();
// 返回所有的枚举实例
Color[] colors = Color.values();
// 获得实例的名称
String colorName = BLACK.name();
// 通过实例名称来获得枚举实例
Color color = Color.valueOf(colorName);
/*
* 比较两个枚举的方法一
*
* 比较方式是比较枚举的ordinal
*/
int compare = BLUE.compareTo(BLUE);
/*
* 比较两个枚举的方法二
*
* 枚举支持直接用这种逻辑表达式方式作比较
*/
boolean isEqual = RED == BLACK;
}
}
1.1 带有构造函数、抽象方法的枚举
1、枚举类的构造方法必须使用private做访问修饰符。
2、当枚举类型中有抽象方法时,在定义枚举类成员的时候,不能直接定义或者仅仅定义调用哪个构造函数的枚举成员,必须同时要求枚举成员实现这个枚举类型的抽象方法,否则编译报错。
含有构造方法和抽象方法的例子:
public enum Color {
RED("BLUE") {
@Override
public void doSomeThing() {
System.out.println(name());
}
},
BLUE("BLACK") {
@Override
public void doSomeThing() {
System.out.println(toString());
}
},
BLACK("RED") {
@Override
public void doSomeThing() {
System.out.println(ordinal());
}
};
private String color;
/**
* 构造函数
*/
private Color(String color) {
this.color = color;
}
public String getColor() {
return color;
}
/**
*
* 定义抽象方法
*
* 实例必须实现它
*/
abstract void doSomeThing();
}
1.2枚举的一些其他应用
枚举支持直接用
switch作选择,
使代码可读性更强。
Color color = Color.RED;
public void change() {
switch (color) {
case RED:
color = Color.BLUE;
break;
case BLUE:
color = Color.BLACK;
break;
case BLACK:
color = Color.RED;
break;
}
}
2. JDK5泛型
在定义泛型类或声明泛型类的变量时,使用尖括号来指定形式类型参数,如List<E>。形式类型参数与实际类型参数之间的关系类似于形式方法参数与实际方法参数之间的关系,只是类型参数表示类型,而不是表示值。
泛型的好处:
1)类型安全。泛型的主要目标是提高 Java 程序的类型安全。将运行期间的类型转换错误移动到编译时期的编译错误
2)消除强制类型转换。消除源代码中的许多强制类型转换
泛型的一些特点
:
1)泛型不是协变的
即对于任何两个不同类型Type1和Type2,List<Type1>既不是List<Type2>的子类型,也不是List<Type2>的超类型。
List<Object> ol = new ArrayList<Integer>();
上述代码会在编译时报类型不兼容错误。
2)泛型中的类型通配符
由于泛型参数化类型是不可变的,对于任何类型的Type1和Type2而言,List<Type1>既不是List<Type2>的子类型,也不是它的超类型,由此会产生可以将任何对象放进List<Object>中,却只能将字符串放在List<String>中的问题,解决此类问题我们需要使用泛型的通配符。
假设有这样一个方法:
public static void showList(List<Object> list){
for (Object o : list)
System.out.println(o);
}
}
当试图用List<Integer>调用它
List<Integer> list = new ArrayList<Integer>();
list.add(2);
showList(list);
则会在编译时报类型不兼容错误,解决方案是使用类型通配符:
public static void showList(List<?> list) {
for (Object o : list)
System.out.println(o);
}
上面代码中的问号是一个类型通配符。
类型通配符的其他用法:
(1). 向下限定 格式:<? extends T>:T限定,T的子类拓展
表示?取值的类型只能是T本身或者其子类。
如:List<? extends Number> list = new ArrayList<Integer>();
Integer是Number的子类
(2). 向上限定 格式:<? super T>:T限定,T的父类拓展
表示?取值的类型只能是T本身或者其父类。
如:List<? super Integer> list = new ArrayList<Number>();
Number 为Integer的父类