第十三章 枚举与泛型

news2024/12/28 19:42:04

13.1枚举类型 

13.1.1 使用枚举类型设置常

设置常量时,通常将常量放置在接口中,这样在程序中直接使用。该常量不能被修改,因为在接口定义常量时,该常量的修饰符为final与static。常规定义常量的代码如下:

public interface Constants{

public static final int Constants_A=1;

public static final int Constants_B=12;

}

枚举类型出现后,逐渐取代了上述常量定义方式。使用枚举类型定义常量的语法如下:

public enum Constants{

        Constants_A,

        Constants_B,

}

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

例题13.1

package shisanzhang;    //例题13.1
interface SeasonInterface{			//四季接口
	int SPRING=1,SUMMER=2,AUTUMN=3,WINTER=4;
}
enum SeasonEnum{					//四季枚举
	SPRING,SUMMER,AUTUMN,WINTER
}
public class SeasonDemo {
 
	public static void printSeason1(int season) {
		switch(season) {
		case SeasonInterface.SPRING:
			System.out.println("这是春季");break;
		case SeasonInterface.SUMMER:
			System.out.println("这是夏季");break;
		case SeasonInterface.AUTUMN:
			System.out.println("这是秋季");break;
		case SeasonInterface.WINTER:
			System.out.println("这是冬季");break;
		default:
		System.out.println("这不是四季的常量值");
		}
 
	}
	public static void printSeason2(SeasonEnum season) {
		switch(season) {
		case SPRING:
			System.out.println("这是春季");break;
		case SUMMER:
			System.out.println("这是夏季");break;
		case AUTUMN:
			System.out.println("这是秋季");break;
		case WINTER:
			System.out.println("这是冬季");break;
		}
}
	public static void main(String[] args) {
		printSeason1(SeasonInterface.SPRING);		//使用接口常量做参数
		printSeason1(3);							//可以使用数字做出参数
		printSeason1(-1);							//使用接口常量值意外的数字“冒充”常量
		printSeason2(SeasonEnum.WINTER);			//使用枚举做参数,只能用枚举中有的值,无法“冒充”
	}
	}

运行结果如下:

13.1.2 深入了解枚举类型 

枚举类型的常用方法如下:

1.values()方法

枚举类型实例包含一个values()方法,该方法可以将枚举类型成员以数组的形式返回

例题13.2

package shisanzhang;                //例题13.2
enum SeasonEnum{                    //四季枚举
    SPRING,SUMMER,AUTUMN,WINTER
}
public class ShowEnum {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SeasonEnum es[]=SeasonEnum.values();
        for(int i=0;i<es.length;i++) {
            System.out.println("枚举常量:"+es[i]);
    }
    }

}

 运行结果如下:

2. valueOf()方法与compareTo()方法

枚举类型中静态方法valueOf()方法可以将普通字符串转换为枚举类型,而compareTo()方法用于比较两个枚举类型对象定义时的顺序。

例题13.3

package shisanzhang;				//例题13.3
enum SeasonEnum{					//四季枚举
	SPRING,SUMMER,AUTUMN,WINTER
}
public class EnumMethodTest {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SeasonEnum tmp=SeasonEnum.valueOf("SUMMER");	//根据字符串创建一个枚举值
		SeasonEnum es[]=SeasonEnum.values();			//获取所有枚举值
		for(int i=0;i<es.length;i++) {
			String message="";							//待输出的消息
			int result=tmp.compareTo(es[i]);			//记录两个枚举的比较结果
			if (result<0) {
				message=tmp+"在"+es[i]+"的前"+(-result)+"个位置";
			}else if(result>0) {
				message=tmp+"在"+es[i]+"的后"+result+"个位置";
			}else if(result==0) {
				message=tmp+"与"+es[i]+"是同一个值";
			}
			System.out.println(message);
		}
			
	}
 
}

 运行结果如下:

3.ordinal()方法

枚举类型中的ordinal()方法用于获取某个枚举对象的位置索引值

例题13.4

package shisanzhang;		//例题13.4
 
enum SeasonEnum{			//四季枚举
	SPRING,SUMMER,AUTUMN,WINTER
}
 
public class EnumIndexTest {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SeasonEnum es[]=SeasonEnum.values();
		for(int i=0;i<es.length;i++) {
			System.out.println(es[i]+"在枚举类型中位置索引值"+es[i].ordinal());
		}
	}
 
}

 运行结果如下:

4.枚举类型中的构造方法

枚举类型定义的构造方法语法如下:

enum 枚举类型名称{
    Constants_A("我是枚举成员A"),
    Constants_B("我是枚举成员B"),
    Constants_C("我是枚举成员C"),
    Constants_D("3"),
    private String description;
    private Constants2(){            //定义默认构造方法
    }
    private Constants2(String description){       //定义带参数的构造方法,参数类型为字符串类型
        this.description = description;
    }
    private Constants2(int i){                //定义带参数的构造方法,参数类型为整型
        this.i=this.i+i;
    }
}

无论是有无参构造方法还是有参构造方法,修饰权限都为private.

例题13.5

 
//例题13.5
enum SeasonEnum{			//四季枚举
	SPRING("万物复苏"),
	SUMMER("烈日炎炎"),
	AUTUMN("秋草枯黄"),
	WINTER("白雪皑皑");
	
	private String remarks;						//枚举的备注
	private SeasonEnum(String remarks) {		//构造方法
		this.remarks="我是"+this.toString()+",我来之后"+remarks+"。";
	}
	String getRemarks() {				//获取备注
		return remarks;
	}
}
public class EnumConstructTest {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SeasonEnum es[]=SeasonEnum.values();
		for(int i=0;i<es.length;i++) {
			System.out.println(es[i].getRemarks());
		}
	}
}

 运行结果如下:

13.1.3 使用枚举类型的优势 


特点:

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


泛型
 

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

回顾向上转型与向下转型

在介绍泛型之前,先来看一个例子,在项目中创建Test类,在该类中使基本类型向上转型为object类型
 

 public class Test {
	private Object b;  //定义object类型成员变量
	public Object getB() { //设置相应的getXXX()方法
	return b;
	}
	public void setB(Object b) { //设置相应的setXXX()方法
		this.b = b;
	}
 
 
	public static void main(String[] args) {
		Test t = new Test();
		t.setB(Boolean.valueOf(true));   //向上转型操作
		System.out.println(t.getB());
		t.setB(Float.valueOf("12.3"));   //向下转型操作
		Float f = (Float)t.getB();
		System.out.println(f);
	}
}

运行结果如下:

在本实例中,Test类中定义了私有的成员变量b,它的类型为Object类型,同时为其定义了相应的setXXX()与getXXX()方法。在类的主方法中,将Boolean.valueOf(true)作为setB()方法的参数,向下转型会出现错误,语法错误没有出现编译器会接受此段代码,,但执行时会出现ClassCastException异常,而泛型机制就有效解决了这一问题。

例如以下代码:
 

    t.setB(Float.valuesOf("12.3"));
    Integer f = (Integer)t.getB();
    System.out.println(f);

定义泛型类

Object类为最上层的父类,为了提前预防发生异常,Java提供了泛型机制其语法如下

类名<T>

例题13.6

 
 
public class Book<T> {  //定义带泛型的Book<T>类
	private T bookInfo;   //类型形参:书籍信息
	public Book(T bookInfo) {    //参数为类型形参的构造方法
		this.bookInfo = bookInfo;   //为书记信息赋值
	}
	public T getBookInfo() {   //获取书籍信息的值
		return bookInfo;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//创建参数为String类型的书名对象
		Book<String>bookName =new Book<String>("《Java从入门到精通》");
		//创建参数为String类型的作者对象
		Book<String>bookAuthor =new Book<String>("明日科技");
		//创建参数为String类型的价格对象
		Book<String>bookPrice =new Book<String>("69.8");
		//创建参数为Boolean类型的附赠源码
		Book<Boolean>hasSource =new Book<Boolean>(true);
		//控制台输出书名、作者、价格和是否附赠光盘
		System.out.println("书名:"+bookName.getBookInfo());
		System.out.println("作者:"+bookAuthor.getBookInfo());
		System.out.println("价格:"+bookPrice.getBookInfo());
		System.out.println("是否附赠源代码?"+hasSource.getBookInfo());
	}
 
}

运行结果如下:

泛型的常规用法

1.定义泛型类时声明多个类型。语法如下:

class MyClass<T1,T2>{ }

T1,T2为可能被定义的类型

 在实例化指定类型的对象时就可以指定多个类型,例如:

MyClass<Boolean,Float> m = new MyClass <Boolean,Float>();

2.定义类型类时声明数组类型

定义泛型类时也可以声明数组类型。

例题13.7定义泛型数组

package b;
 
public class ArrayClass<T> {
	private T[] array;    //定义泛型数组
	public T[] getArray() {
		return array;
	}
	public void setArray(T[] array) {
		this.array =array;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrayClass<String>demo =new ArrayClass<String>();
		String value[] = {"成员1","成员2","成员3","成员4","成员5"};
		demo.setArray(value);
		String array[]=demo.getArray();
		for (int i =0;i<array.length;i++) {
			System.out.println(array[i]);
		}
	}
 
}

 运行结果如下:

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

3.集合类声明容器的元素

JDK中的集合接口、集合类都被定义了泛型,其中List<E>的泛型E实际上就是element元素的首字母,Map<K,V>的泛型K和V就是key键和value值的首字母。常用的被泛型化的集合类如下表:

例题13.8

 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
 
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));        // 根据键名获取键值
		}
	}
}
//例题13.8

 运行结果如下:

13.2.4 泛型的高级用法

泛型的高级用法包括限制泛型可用类型和使用类型通配符等。

1.限制泛型可用类型

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

class 类名称<T extends anyClass>

 例题13.9

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) {
				// 可以实例化已经实现List接口的类
				LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();
				LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();
				// 这句是错误的,因为HashMap没有实现List()接口
				LimitClass<HashMap> l3 = new LimitClass<HashMap>();
				
			}
 
}

运行结果如下:

出现异常:异常为Hasamap不能·被实例化

如果我们想它不报错的话就将hash map改为导入类中的list。但仍然无法运行,只是不报错。如下

 
	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) {
				// 可以实例化已经实现List接口的类
				LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();
				LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();
				// 这句是错误的,因为HashMap没有实现List()接口
				LimitClass<List> l3 = new LimitClass<List>();
				
			}
 
}

2.使用类型通配符

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

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

其中,<? extends List>表示类型未知,当需要使用该泛型对象时,可以单独实例化,例如:

A <?extends List> a=null;//定了上界和下界

a=new A<ArraryList>();

a=new A<ArraryLinkList>();

像上述例子的HashMap类没有实现List接口,那编译器就会报错.除了可以实例化一个限制泛型类型的实例,还可以将该实例放置在方法的参数

public void do Something(A<? extendsList>a){} 

在上述代码中,定义方式有效地限制了传入do Something()方法的参数类型。如果使用A<?>这种形式实例化泛型类对象,则默认表示可以将a指定为实例化Object及以下的子类类型,例如:

List <String>l1 = new ArraryList<String>();    //实例化一个对象

l1.add("成员");                      //在集合中添加内容

List<?>l2=l1;

List<?>l3 = new LinkkedList<integer>();

System.out.println(2.get(0));    //获取集合中第一个值

在上面的例子中list类型的对象可以接受时君类型的和ArraryList集合也可以接受Integer类型的LLinkedList集合。

注意:List<?>12=11和List12=11有区别
使用通配符声明的名称实例化的对象不能对其加入新的信息,只能获取或删除。例如:

.set(0,"成员改变");     //没有使用通配符的对象调用set()方法

//l2.set(0,"成员改变");//使用通配符的对象调用set()方法,不能被调用。

//l3.set(0,1);

l2.get(0);  //可以使用l2的获取集合中的值

l2.remove(0);//根据键名删除集合中的值

3.继承泛型类与接口

定义为泛型的类和接口也可以被继承与实现。例如让Subclass类继承Extendclass类的泛型,代码入下:

class Extend Class <T1>{}

Class Sub Class <T1,T2,T3>extends Extend Class <T1>{}

如果在Sub Class类继承Extend Class类时保留父类的泛型类型,需要在继承时期指明。如果没有指明,直接使用extends Extends Class语句进行继承操作,则SubClass类中的 T1T2和T3都会自动变为object类型,所以在一般情况下都将父类的泛型类型保留。

        定义为泛型的接口也可以被实现,例如让Sub Class类实现Some Interface接口,并继承接口的泛型。代码如下:
 

interface SomeInterface<T1>{}

class SubClass<T1,T2,T3>implements SomeInterface<T1>{}

13.2.5 泛型总结

总结一下泛型的使用方法。

1泛型类型参数只能是类类型,不可以是简单类型,比如A< int>这种泛型定义就是错误的。

2.泛型的类型个数可以是多个

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1148644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Stable Diffusion系列(一):古早显卡上最新版 WebUI 安装及简单操作

文章目录 Stable Diffusion安装AnimateDiff插件适配sdxl模型适配 Stable Diffusion使用插件安装界面设置基础文生图加入lora的文生图 Stable Diffusion安装 我的情况比较特殊&#xff0c;显卡版本太老&#xff0c;最高也就支持cuda10.2&#xff0c;因此只能安装pytorch1.12.1&…

05、SpringCloud -- 秒杀按钮、秒杀请求流程(各种请求到后台的判断、减库存、下单数据和次数保存)

目录 秒杀按钮代码实现:vue的JS实现:秒杀请求需求:代码前端后端Seckill-apidomainSeckill-serverWebConfig1、秒杀请求判断controller2、重复下单判断MapperService 接口Impl 实现类controller3、库存判断4、秒杀涉及到的操作_01、减库存_02、创建订单对象并保存_03、用户下…

mycat2.X读写分离

一、数据库中间件介绍 二、下载安装包 2.1下载地址: 下载两个一个是mycat程序,一个是mycat的驱动 http://dl.mycat.org.cn/2.0/install-template/mycat2-install-template-1.20.zip http://dl.mycat.org.cn/2.0/1.21-release/mycat2-1.21-release-jar-with-dependencies-2…

电子邮件钓鱼攻击的防范:如何识别并避免网络诈骗

在数字化的今天&#xff0c;电子邮件成为我们日常工作和生活中不可或缺的通讯工具。然而&#xff0c;电子邮件钓鱼攻击也随之成为网络诈骗的常见手法。通过识别和避免电子邮件钓鱼攻击&#xff0c;我们可以在很大程度上保护自己的网络安全。本文将为您提供一些实用的识别和防范…

nacos在linux中的安装、集群的配置、mysql生产配置

1.下载和安装 官方下载地址&#xff1a;https://github.com/alibaba/nacos/releases&#xff0c;根据自己需要的本版去下载就行 下载的是 .tar.gz 后缀的文件是linux版本的 使用tar命令解压&#xff0c;完成之后是一个nacos的文件夹 和windows下的文件夹目录是一样的 要启…

小黑子—spring:第三章 AOP开发

spring入门3.0 三 小黑子的springAOP开发1. AOP简介1.1 AOP的概念1.2 AOP思想的实现方案1.3 模拟AOP思想实现的基础代码1.4 AOP的相关概念 2. 基于xml配置的AOP2.1 XML方式AOP快速入门2.2 XML方式AOP配置详解2.3 xml方式AOP的原理解析2.3.1 AOP底层两种生成Proxy的方式 3. 基于…

一个老旧优盘从2M变回8G的逆袭之路

前言 最近收拾资料&#xff0c;发现了一个比较老的优盘&#xff0c;上面标记8G内存&#xff0c;就好奇里边存了点啥。用电脑打开&#xff0c;啥内容都没有&#xff0c;结果大小还显示2M&#xff1f;&#xff1f;&#xff1f;看看今天能不能救活吧。 正文 步骤一、清空磁盘 …

并发安全问题之超卖问题

并发安全问题之超卖问题 乐观锁总结&#xff1a; 优点&#xff1a;不加锁性能好。 缺点&#xff1a;同时请求成功率低&#xff08;即只要发现数据变了就放弃了&#xff09;。 乐观锁思想的具体体现&#xff1a;一共两步&#xff0c;第一步&#xff0c;先查询状态。第二步&…

Java VMTranslator Part I

目录 堆栈运算命令 基本思路 核心代码 Parser Code Writer Main 实验结果&#xff0c;使用SimpleAdd、StackTest进行验证 内存访问命令 基本思路 核心代码 Parser Code Writer Main 实验结果&#xff0c;使用进行验证。对比生成的二进制代码文件。 用Java写一个翻…

MySQL6:索引使用原则,联合索引,联合主键/复合主键,覆盖索引、什么是回表?索引条件下推,索引的创建与使用,索引的创建与使用,索引失效

MySQL6&#xff1a;索引使用原则&#xff0c;联合索引&#xff0c;联合主键/复合主键&#xff0c;覆盖索引、什么是回表&#xff1f;索引条件下推&#xff0c;索引的创建与使用&#xff0c;索引的创建与使用&#xff0c;索引失效 索引使用原则列的离散(sdn)度 联合索引创建联合…

【C++初探:简单易懂的入门指南】二

【C初探&#xff1a;简单易懂的入门指南】二 1.引用1.1引用做函数的参数1.2 引用做返回值1.2.1 关于引用做返回值的几点补充 1.3 多引用(对一个变量取多个别名)1.4 引用类型一致性原则以及权限的问题阐述1.5引用的效率问题1.6引用和指针的比较 2.auto关键字2.1 auto关键字的使用…

BSTree二叉树讲解

二叉搜索树的概念&#xff1a; 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值…

重置 VCSA 6.7 root密码和SSO密码

原贴地址&#xff1a;https://www.cnblogs.com/airoot/p/16059033.html 问题描述 1、用root用户登录 VMware vCenter Server Appliance虚拟机失败&#xff0c;无法登录 2、vCenter Server Appliance 6.7 U1的root帐户错误尝试次数超过3次已锁定或帐户已过期 官方说明 在VC…

【Spring Boot 源码学习】RedisAutoConfiguration 详解

Spring Boot 源码学习系列 RedisAutoConfiguration 详解 引言往期内容主要内容1. Spring Data Redis2. RedisAutoConfiguration2.1 加载自动配置组件2.2 过滤自动配置组件2.2.1 涉及注解2.2.2 redisTemplate 方法2.2.3 stringRedisTemplate 方法 总结 引言 上篇博文&#xff0…

【C++基础入门】44.C++中对象模型分析(上)

一、回归本质 class 是一种特殊的 struct 在内存中 class 依旧可以看作变量的集合class 与 struct 遵循相同的内存对齐规则class 中的成员函数与成员变量是分开存放的 每个对象有独立的成员变量所有对象共享类中的成员函数值得思考的问题 下面看一个对象内存布局的代码&#x…

Go学习第十七章——Gin中间件与路由

Go web框架——Gin中间件与路由 1 单独注册中间件1.1 入门案例1.2 多个中间件1.3 中间件拦截响应1.4 中间件放行 2 全局注册中间件3 自定义参数传递4 路由分组4.1 入门案例4.2 路由分组注册中间件4.3 综合使用 5 使用内置的中间件6 中间件案例权限验证耗时统计 1 单独注册中间件…

Java项目之网络考试系统

视频教程&#xff1a; 01-创建数据库_哔哩哔哩_bilibili 源码下载&#xff1a;百度网盘 请输入提取码 准备工作 创建数据库配置IDEA后端导入前端 前言&#xff1a; 把代码掰开写进博客里&#xff0c;主要是让自己在整理笔记的过程中&#xff0c;多去思考完成这个功能的核心…

基于深度学习的单图像人群计数研究:网络设计、损失函数和监控信号

摘要 https://arxiv.org/pdf/2012.15685v2.pdf 单图像人群计数是一个具有挑战性的计算机视觉问题,在公共安全、城市规划、交通管理等领域有着广泛的应用。近年来,随着深度学习技术的发展,人群计数引起了广泛的关注并取得了巨大的成功。通过系统地回顾和总结2015年以来基于深…

rust学习——智能指针Rc

文章目录 Rc 与 ArcRcRc::clone观察引用计数的变化不可变引用一个综合例子Rc 简单总结 多线程无力的 RcArcArc 的性能损耗 总结 Rc 与 Arc Rust 所有权机制要求一个值只能有一个所有者&#xff0c;在大多数情况下&#xff0c;都没有问题&#xff0c;但是考虑以下情况&#xff1…

二维码智慧门牌管理系统升级解决方案:采集要素为智慧城市建设提供精准数据支持

文章目录 前言一、二维码智慧门牌管理系统的升级需求二、采集要素在系统升级中的应用三、消防栓、井盖等采集要素的应用 前言 随着城市化进程的加速&#xff0c;智慧城市的建设已成为未来城市发展的必然趋势。其中&#xff0c;二维码智慧门牌管理系统作为智慧城市的重要组成部…