枚举类型与泛型

时间:2021-08-23 19:25:18

JDK1.5中新增了枚举类型和泛型,枚举类型可以取代以往常量的定义方式,将常量封装在类或接口中,还提供了安全检查功能。枚举类型本质上还是以类的形式存在。泛型的出现不仅可以让程序员少写很多代码,主要的作用是解决类型安全问题,提供编译时的安全检查,不会因为将对象置于某个容器中而失去类型。

  • 枚举类型
以往定义常量的方式使用接口,这样在程序中可以直接被使用,而且该常量不能被修改,接口中定义常量是修饰符为final和static,如下实例:

package enumeration.simple;

public interface ConstantDemos {
public static final int Constants_A = 1;
public static final int Constants_B = 12;
}
JDK1.5以后采用枚举类型代替常量定义方式:

package enumeration.simple;

public enum Constants {
Constants_A,
Constants_B,
Constants_C
}
其中enum为定义枚举类型的关键字,可以通过Constants.Constants_A的方式进行调用。
编译器即使没有接收到接口中定义的常量参数,也不会报错;但如果是枚举类型,该方法就只能接收枚举类型的常量作为参数,其他任何形式都会报错。枚举类型与传统定义常量的方式相比具有类型检测的功能。

package enumeration;


interface Constants1{
public static final int CONSTANTS_A = 1;
public static final int CONSTANTS_B = 2;
}
public class ConstantsTest {
enum Constants2 {
CONSTANTS_A, CONSTANTS_B
}
public static void doit(int c){
switch(c){
case Constants1.CONSTANTS_A:
System.out.println("diot: CONSTANTS_A");
break;
case Constants1.CONSTANTS_B:
System.out.println("diot: CONSTANTS_B");
break;
}
}
public static void doit2(Constants2 c){
switch(c){
case CONSTANTS_A:
System.out.println("diot2: CONSTANTS_A");
break;
case CONSTANTS_B:
System.out.println("diot2: CONSTANTS_B");
break;
}
}
public static void main(String[] args) {
// 不接收常量参数也不会报错
ConstantsTest.doit(Constants1.CONSTANTS_A);
// 必须是枚举类型
ConstantsTest.doit2(Constants2.CONSTANTS_A);
ConstantsTest.doit2(Constants2.CONSTANTS_B);
ConstantsTest.doit(3);
}
}
另外,枚举类型可以看作是一个类,而每个枚举类型成员都可以看作是枚举类型的一个实例,枚举类型成员默认都是被final、public、static修饰。而且枚举类型的类都继承自java.lang.Enum类,该类中有操作枚举类型的方法:

values():将枚举类型的成员以数组的形式返回;

valueOf():将普通字符串转为枚举类型的实例;

compareTo():用于比较两个枚举对象在定义时的顺序;

ordinal():用于得到枚举成员的索引位置;

package enumeration;

public class ShowEnum {
enum Constants2{
Constants_a, Constants_b
}
public static void compare(Constants2 c){
for(int i = 0; i < Constants2.values().length; i++){
System.out.println(c + " and " + Constants2.values()[i] + " compare and result is " + c.compareTo(Constants2.values()[i]));
}
}
public static void main(String[] args) {
for(int i = 0; i < Constants2.values().length; i++){
System.out.println(Constants2.values()[i]);
}
compare(Constants2.Constants_a);
for(int i = 0; i < Constants2.values().length; i++){
System.out.println(Constants2.values()[i].ordinal());
}
}
}
package enumeration;public class EnumIndexTest {enum Constants2{Constants_A, Constants_B, Constants_C, Constants_D;}public static void main(String[] args) {for(int i = 0; i < Constants2.values().length; i++){System.out.println(Constants2.values()[i] + "---" + Constants2.values()[i].ordinal());}}}
枚举类型种可以添加构造方法,但是规定必须为private修饰符锁修饰。

package enumeration.simple;

public class EnumIndexTest {
enum Constants{
Constants_A("a"),
Constants_B("b"),
Constants_C(1);

private String des;
private int i = 4;

private Constants(){

}

private Constants(String des){
this.des = des;
}

private Constants(int i){
this.i = this.i + i;
}

public String getDes(){
return des;
}

public int getI(){
return i;
}
}
public static void main(String[] args) {
for(int i = 0; i < Constants.values().length; i++){
System.out.println(Constants.values()[i] + "---" + Constants.values()[i].getDes());
}
System.out.println(Constants.valueOf("Constants_C") + "---" + Constants.valueOf("Constants_C").getI());
}
}
使用枚举类型的优势为:

类型安全;

紧凑有效的数据定义;

运行效率高;

可以和程序其他部分完美交互;

  • 泛型
在没有泛型之前,Java也提供了对Object的引用任意化的 操作,对Object引用进行向下转型及向上转型(通常向下转型会出现问题),但是某些强制类型转换不会被编译器捕捉,而在运行时出现异常,所以出现了泛型机制。

T代表一个类型的名称。

package genericity;

public class OverClass<T> {
private T over;

public T getOver(){
return over;
}

public void setOver(T over){
this.over = over;
}

public static void main(String[] args) {
OverClass<Boolean> over1 = new OverClass<Boolean>();
OverClass<Float> over2 = new OverClass<Float>();
over1.setOver(true);
over2.setOver(67.9F);
System.out.println(over1.getOver());
System.out.println(over2.getOver());
}
}
使用泛型这种形式将不会发生ClassCastException异常,因为在编译器中就可以检查类型匹配是否正确。
定义泛型类时声明数组类型

package genericity;

public class ArrayClass<T> {
private T[] array;

public void setT(T[] array){
this.array = array;
}

public T[] getT(){
return array;
}

public static void main(String[] args) {
ArrayClass<String> a = new ArrayClass<String>();
String[] arr = {"num1", "num2", "num3", "num4"};
a.setT(arr);
for(int i = 0; i < a.getT().length; i++){
System.out.print(a.getT()[i] + " ");
}
}
}
可以在使用泛型机制时声明一个数组,但是不可以使用泛型来建立数组的实例。
常用的被泛型化的集合类:

ArrayList<E>、HashMap<K,V>,HashSet<E>,Vector<E>;

限制泛型可用类型

class 类名称<T extends anyClass>,其中anyClass可以是类或接口,但都必须使用extends关键字。

package genericity;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class LimitClass<T extends List> {
LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();
LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();
LimitClass<List> l3 = new LimitClass<List>();
}
使用类型通配符

泛型类名称<? extends List> a = null;

A<? extends List> a = null;

a = new A<ArrayList>();

a = new A<LinkedList>();

注意:使用通配符创建出来的集合对象,不能改变集合中的值。

定义为泛型的类和接口也可以被继承与实现,

package genericity;

public class ExtendClass<T1> {
class SubClass<T1, T2, T3> extends ExtendClass<T1>{}
}
package genericity;public interface i<T1> {class SubClass<T1, T2, T3> implements i<T1>{}}
泛型总结:

泛型的类型参数只能是类类型,不能是简单基本类型,如A<int>这种方式定义是错误的;

泛型的类型参数可以是多个;

可以使用extends关键字限制泛型的类型;

可以使用通配符限制泛型的类型;