天天看点

20190118——Java从入门到精通 第十七章 枚举类型与泛型

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

枚举类型

JDK中新增了枚举类型,可以使用该功能取代以往定义常量的方式,同时枚举类型还赋予程序在编译时进行检查的功能。

使用枚举类型设置常量

以往设置常量,通常将常量放置在接口中,这样在程序中就可以直接使用,并且该常量不能修改,因为在接口中定义常量,该常量的修饰符为final与static。

package chapter17;

public class ConstantsTest {
    enum Constants2{
        Constants_A,Constants_B
    }
    public static void doit(int c ){
        switch (c) {
            case Constants.Constants_A:
                System.out.println("doit()Constants_A");
                break;
            case Constants.Constants_B:
                System.out.println("doit()Constants_B");
                break;
        }
    }
    public static void  doit2(Constants2 c){
        switch (c){
            case Constants_A:
                System.out.println("doit2()Constants_A");
                break;
            case Constants_B:
                System.out.println("doit2()Constants_B");
                break;
        }
    }

    public static void main(String[] args) {
        ConstantsTest.doit(Constants.Constants_A);
        ConstantsTest.doit2(Constants2.Constants_A);
        ConstantsTest.doit2(Constants2.Constants_B);
        ConstantsTest.doit(3);
        
    }
}

           
20190118——Java从入门到精通 第十七章 枚举类型与泛型

当用户调用doit()方法时,即使编译器不接受在接口中定义的常量参数,也不会报错;但是调用doit2()方法,任意传递参数,编译器就会报错,因为这个方法值接受枚举类型的常量作为其参数

深入了解枚举类型

枚举类型较传统定义常量的方式,除了具有参数类型检测的优势之外,还具有其他方面的优势。

用户可以将一个枚举类型看做成是一个类,它继承于java.lang.Enum类,当定义一个枚举类型时,每一个枚举类型成员都可以看作是一个枚举类型的实例,这些枚举类型成员都默认被final、public、static修饰,所以当使用枚举类型成员时直接使用枚举类型名称调用枚举类型成员即可。

由于枚举类型对象继承于java.lang.Enum类,所以该类中一些操作枚举类型的方法都可以应用到枚举类型中

values() 该方法可以将枚举类型成员以数组的形式返回 枚举类型名称.values() Constant2.values()

valueOf() 该方法可以实现将普通字符串转换成枚举实例 枚举类型名称.valueOf(“abc”) Constants.valueOf(“abc”)

compareTo() 该方法用于比较两个枚举对象的定义时的顺序 枚举对象.compareTo() Constants_A.compareTo(Constant_B)

ordinal() 该方法用于得到枚举成员的位置索引 枚举对象.ordinal() Constants_A.ordinal()

枚举类型中的构造方法

在枚举类型中,可以添加构造方法, 但是规定这个构造方法必须为private修饰符所修饰。

从枚举类型构造方法的语法中可以看出,无论是无参构造方法还是有参构造方式,修饰权限都为private。定义一个有参构造方法后,需要对枚举类型成员相应地使用该构造方法,如Constants_A,相应地使用了参数为String型和参数为int型的构造方法。然后可以在枚举类型中定义两个成员变量,在构造方法中为这两个成员变量赋值,这样就可以在枚举类型中定义该成员变量的getXXX()方法

使用枚举类型的优势

特点:类型安全,紧凑有效的数据定义,可以和程序其他部分完美交互,运行效率高

泛型

在JDK1.5版本中提供了泛型概念,泛型实质上就是程序员定义安全的类型,在没有出现泛型之前,Java也提供了Object的引用“任意化”操作,这种任意化操作就是对Object引用进行向下转型或者向上转型操作,但某些强制类型转换的错误也许不会被编译器捕捉,而在运行后出现异常,可见强制类型转换存在安全隐患,所以在此提供了泛型机制。

定义泛型类

Object类为最上层的父类,很多程序为了使程序更为通用,设计程序时通常使传入的值与返回的值都以Object类型为主+,当需要使用这些实例时,必须正确地将该实例转换为原来的类型,否在在运行时将会发生ClassCastException异常

在JDK1.5版本以后,提出了泛型机制

类名<T>
           

T代表一个类型的名称

package chapter17;

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(12.3f);
        Boolean b=over1.getOver();
        Float f=over2.getOver();
        System.out.println(b);
        System.out.println(f);

    }
}

           
20190118——Java从入门到精通 第十七章 枚举类型与泛型

在类名后面添加了一个

<T>

语句,这里使用了泛型机制,可以将OverClass类称为泛型类,同时返回和接受的参数使用T这个类型。最后在主方法中可以使用Over《boolean》形式返回一个boolean类型的对象,使用OverClass<Float 形式返回一个float型的对象,使这两个对象分别代用setOver方法不需要进行显示向上转型操作,setOver()方法直接接受相应类型的参数,而代用getOver()方法时,不需要进行向下转型操作,直接将getOver()方法返回的值赋予相应的类型变量即可。

使用泛型定义的类在声明该类对象时可以根据不同的需求制定<T 真正的类型,而在使用类中的方法传递或返回数据类型时将不再需要进行类型转换操作,而是使用在声明泛型类对象“”《》符号中设置的数据类型。

使用泛型这种形式将不会发生ClassCastException异常,因为在编译器中就可以检查类型匹配是否正确

在定义泛型时,一般类型名称使用T来表达,而容器的元素使用E来表达,具体的设置读者可以参看JDK5.0以上的版本的API

泛型的常规用法

定义反省类型时声明多个类型

MutiOverClass<T1,T2>
           

这样在实例化指定类型的对象时就可以指定多个类型

定义泛型类时声明数组类型

定义泛型类时声明一个成员数组,数组的类型为泛型,然后在泛型类中响应设置set/get方法

可见,可以在使用泛型机制时声明一个数组,但是不可以使用泛型来建立数组的实例。

集合类声明容器的元素

可以使用K和V两个字符代表容器中的键值与键值对应的具体值

泛型的高级用法

限制泛型可用类型

默认可以使用任何类型来实例化一个泛型类对象,但Java中也对泛型类实例的类型做了限制

class 类名<T extends anyClass>
           

其中anyClass指某个接口或类

使用泛型限制后,泛型类的类型必须实现或继承了anyClass这个接口或者类,无论anyClass是接口还是类,在进行泛型限制时都必须使用extends关键字。

package chapter17;

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

public class LimitClass <T extends List> {
    public static void main(String[] args) {
        LimitClass<ArrayList> l1=new LimitClass<>();
        LimitClass<LinkedList> l2=new LimitClass<>();
        //LimitClass<HashMap> l3 =new LimitClass<HashMap>();
        //这句话是错误的,因为HashMap没有实现List()接口
    }
} 

           

将泛型做了限制,设置泛型类型必须实现list接口。ArrayList和LinkedList都实现了List接口,而HashMap没有实现List接口,所以在这里不能实例化HashMap类型的泛型对象

当没有使用extends关键限制泛型类型时,默认Object类下的所有子类都可以实例化泛型类对象

使用类型通配符

在泛型机制中,提供了类型通配符,其主要作用是在创一个泛型类对象时限制这个泛型类的类型实现或继承某个接口或类的子类,要声明这样一个对象可以使用“?”通配符来表示,同时使用extends关键字来对泛型加以限制。

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