第十七章 枚举类型与泛型

枚举类型与泛型

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

枚举类型

使用枚举类型设置常量

使用枚举类型定义常量的语法如下:

public enum Constants{
	Constants_A,
	Constants_B,
	Constants_C
}

其中,enum是定义枚举类型关键字。当需要在程序中使用该常量时,可以使用Constants.Constants_A来表示。

深入了解枚举类型

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

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

操作枚举类型成员的方法

枚举类型常用方法:

方法名称具体含义使用方法
values()将枚举类型成员以数组的形式返回枚举类型名称.values()
valueOf()将普通字符串转换为枚举实例枚举类型名称.valueOf(“abc”)
compareTo()比较两个枚举对象在定义时的顺序枚举对象.compareTo()
ordinal()得到枚举成员的位置索引枚举对象.ordinal()
枚举类型中的构造方法
  • 规定枚举类型的构造方法必须为private修饰符所修饰,以防止客户代码实例化一个枚举对象。

定义一个有参构造方法后,需要对枚举类型成员相应地使用该构造方法 例:

import static java.lang.System.*;

public class EnumIndexTest {
	enum Constants2 { // 将常量放置在枚举类型中
		Constants_A("我是枚举成员A"), // 定义带参数的枚举类型成员
		Constants_B("我是枚举成员B"), Constants_C("我是枚举成员C"), Constants_D(3);
		private String description;
		private int i = 4;
		
		private Constants2() {
		}
		 // 定义参数为String型的构造方法
		private Constants2(String description) {
			this.description = description;
		}
		
		private Constants2(int i) { // 定义参数为整型的构造方法
			this.i = this.i + i;
		}
		
		public String getDescription() { // 获取description的值
			return description;
		}
		
		public int getI() { // 获取i的值
			return i;
		}
	}
	
	public static void main(String[] args) {
		for (int i = 0; i < Constants2.values().length; i++) {
			out.println(Constants2.values()[i] + "调用getDescription()方法为:"
					+ Constants2.values()[i].getDescription());
		}
		out.println(Constants2.valueOf("Constants_D") + "调用getI()方法为:"
				+ Constants2.valueOf("Constants_D").getI());
	}
}

在这里插入图片描述

此外,还可以将这个getDescription()方法设置在接口中,使枚举类型实现该接口。例:

package com.lzw;
import static java.lang.System.*;
interface d {
	public String getDescription();
	
	public int getI();
}

public enum AnyEnum implements d {
	Constants_A { // 可以在枚举类型成员内部设置方法
		public String getDescription() {
			return ("我是枚举成员A");
		}
		
		public int getI() {
			return i;
		}
	},
	Constants_B {
		public String getDescription() {
			return ("我是枚举成员B");
		}
		
		public int getI() {
			return i;
		}
	},
	Constants_C {
		public String getDescription() {
			return ("我是枚举成员C");
		}
		
		public int getI() {
			return i;
		}
	},
	Constants_D {
		public String getDescription() {
			return ("我是枚举成员D");
		}
		
		public int getI() {
			return i;
		}
	};
	private static int i = 5;
	
	public static void main(String[] args) {
		for (int i = 0; i < AnyEnum.values().length; i++) {
			out.println(AnyEnum.values()[i] + "调用getDescription()方法为:"
					+ AnyEnum.values()[i].getDescription());
			out.println(AnyEnum.values()[i] + "调用getI()方法为:"
					+ AnyEnum.values()[i].getI());
		}
	}
}

使用枚举类型的优势

枚举类型的特点:

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

泛型

泛型实质上就是是程序员定义安全的类型
强制类型转换存在安全隐患,所以提供了泛型机制

定义泛型类

语法:

类名<T>

其中,T代表一个类型的名称。

在定义泛型类时,一般类型名称使用 T 来表达,而容器的元素使用 E 来表达。

泛型的常规用法

定义泛型类时声明多个类型

在定义泛型类时,可以声明多个类型。例:

MutiOverClass<T1,T2>

则:

MutiOverClass<Boolean,Float> = new MutiOverClass<Boolean,Float>();
定义泛型类时声明数组类型

例:

public class ArrayClass<T> {
	private T[] array; // 定义泛型数组
	
	public void SetT(T[] array) { // 设置SetXXX()方法为成员数组赋值
		this.array = array;
	}
	
	public T[] getT() { // 获取成员数组
		return array;
	}
	
	public static void main(String[] args) {
		ArrayClass<String> a = new ArrayClass<String>();
		String[] array = { "成员1", "成员2", "成员3", "成员4", "成员5" };
		a.SetT(array); // 调用SetT()方法
		for (int i = 0; i < a.getT().length; i++) {
			System.out.println(a.getT()[i]); // 调用getT()方法返回数组中的值
		}
	}
}

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

public class ArrayClass<T>{
	//private T[] array = new T[10]; //不能使用泛型来简历数组的实例
}
集合类声明容器的元素

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

public Map<K,V> m = new HashMap<K,V>();
import java.util.*;

public class AnyClass {
	public static void main(String[] args) {
		// 定义ArrayList容器,设置容器内的值类型为Integer
		ArrayList<Integer> a = new ArrayList<Integer>();
		a.add(1); // 为容器添加新值
		for (int i = 0; i < a.size(); i++) {
			// 根据容器的长度循环显示容器内的值
			System.out.println("获取ArrayList容器的值:" + a.get(i));
		}
		// 定义HashMap容器,设置容器的键名与键值类型分别为Integer与String型
		Map<Integer, String> m = new HashMap<Integer, String>();
		for (int i = 0; i < 5; i++) {
			m.put(i, "成员" + i); // 为容器填充键名与键值
		}
		for (int i = 0; i < m.size(); i++) {
			 // 根据键名获取键值
			System.out.println("获取Map容器的值" + m.get(i));
		}
		// 定义Vector容器,使容器中的内容为String型
		Vector<String> v = new Vector<String>();
		for (int i = 0; i < 5; i++) {
			v.addElement("成员" + i); // 为Vector容器添加内容
		}
		for (int i = 0; i < v.size(); i++) {
			// 显示容器中的内容
			System.out.println("获取Vector容器的值" + v.get(i));
		}
	}
}

详情看集合类

泛型的高级用法

 泛型的高级用法包括 限制泛型可用类型 和 使用类型通配符
限制泛型可用类型
class 类名称<T extends anyClass>

其中,anyClass指某个接口或类。

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

import java.util.*;
public class LimitClass<T extends List>{//限制泛型的类型
	public static void main(String[] args){
	//可以实例化已经实现List接口的类
	LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();
	LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();
	//这句是错误的,因为HashMap没有实现List()接口
	//LimitClass<HashMap> l3 = new LImitClass<HashMap>();
	}
}
使用类型通配符
泛型类型名称<? extends List> a = null;

除了可以实例化一个限制泛型类型的实例之外,还可以将实例放置在方法的参数中。如:

public void doSomething(A<? extends List> a){
}
通过通配符声明的名称实例化的对象不能对其加入新的信息,只能获取或删除

泛型类型限制还可以使用super进行向上限制,如:

A<? super ArraytList> a = null;
  • 因为一开始学这个有点懵,所以查了下资料,对上述限制泛型可用类型和使用类型通配符做了个认识和比较。
  • 通配符使用通常是因为不知道接收端会传来什么类型的函数,因此设置的时候直接用 ? 代表接收任何类型的函数都行。
    详情查看JAVA泛型与通配符详解
继承泛型类和实现泛型接口
  1. 定义为泛型的类和接口也可以被继承与实现。
  2. 定义的泛型接口也可以被实现。

泛型总结

使用方法:

  • 泛型的类型参数只能是类类型,不可以是简单类型,如A这种泛型定义就是错误的。
  • 泛型的类型个数可以是多个
  • 可以使用extends关键字限制泛型的类型。
  • 可以使用通配符限制泛型的类型。

实践与练习

  1. 定义一个泛型类,使用extends关键字限制该泛型类的类型为List接口,并分别创建两个反省对象。
  2. 尝试定义一个泛型类,并使用通配符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值