Java枚举类型与泛型

article/2025/10/11 19:31:27

一、枚举类型

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,Constants_C
}

例:

interface Constants { // 将常量放置在接口中public static final int Constants_A = 1;public static final int Constants_B = 12;
}public class ConstantsTest {enum Constants2 { // 将常量放置在枚举类型中Constants_A, Constants_B}// 使用接口定义常量public static void doit(int c) { // 定义一个方法,这里的参数为int型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);// ConstantsTest.doit2(3);	// 必须为枚举中定义的常量}
}

输出:

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

    枚举类型也可在类的内部进行定义,如:

public class ConstantsTest {enum Constants2{ /将常放在枚举类型中Constants A,Constants_ B}
}

        这种形式类似于内部类形式,当编译该类时,除了ConstantsTest.class 外,还存在Constants-Test$1.class 与ConstantsTest$Constants2.class文件。

 

2、枚举类型常用方法

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

       注:调用compareTo()方法返回的结果,正值代表方法中参数在调用该方法的枚举对象位置之前; 0代表两个互相比较的枚举成员的位置相同;负值代表方法中参数在调用该方法的枚举对象位置之后。

例:

import static java.lang.System.*;public class EnumMethodTest {enum Constants2 { // 将常量放置在枚举类型中Constants_A, Constants_B}// 定义比较枚举类型方法,参数类型为枚举类型public static void compare(Constants2 c) {// 根据values()方法返回的数组做循环操作for (int i = 0; i < Constants2.values().length; i++) {// 将比较结果返回out.println(c + "与" + Constants2.values()[i] + "的比较结果为:"+ c.compareTo(Constants2.values()[i]));}}// 在主方法中调用compare()方法public static void main(String[] args) {compare(Constants2.valueOf("Constants_B"));}
}

输出:

 

3、枚举类型中的构造方法

       在枚举类型中,可以添加构造方法,但是规定这个构造方法必须为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());}
}

输出:

       注:在这里将枚举类型的构造方法设置为private修饰,以防止客户代码实例化一个枚举类型。

       除了可以使用上例中所示的方式定义getDescription()方法获取枚举类型成员定义时的描述之外,还可以将这个getDescription()方法放置在接口中,使枚举类型实现该接口,然后使每个枚举类型实现接口中的方法。

例:

interface d{public String getDescriprion();public int getI();
}public enum AnyEnum implements d{Constants_A{public String getDescriprion() {return("枚举A");}public int getI() {return i;}},	Constants_B{public String getDescriprion() {return("枚举B");}public int getI() {return i;}};static int i = 5;
}

 

小结:

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

 

二、泛型

       在以往的类型转换时通常有两种类型,一种是向上转型操作,如Boolen转换为Object,另一种是向下转型操作,如Object转换为Float。在这里向上转型一般是安全的,而如果进行向下转型操作时用错了类型,或者并没有执行该操作,就会出现异常,而泛型机制有效地解决了这一问题。泛型机制语法如下:

类名<T>

1、泛型的常规用法

(1)定义泛型时声明多个类型

MutiOverClass<T1, T2>
MutiOverClass:泛型类名称

(2)定义泛型类型时声明数组类型

       定义泛型时也可声明数组类型,但是要注意不可以使用泛型来建立数组的实例。

例:

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()方法返回数组中的值}}
}

输出:

(3)集合类声明容器的元素

       可以使用K和V两个字符代表容器中的键值和与键值相对应的具体值。常用的被泛型化的集合类如下:

      由于被泛型化的集合类已经是属于泛型,故不需要再定义泛型类,可直接使用如下所示语句实例化:

例:

public Map<K, V> m = new HashMap<K, V>();

例:

import java.util.*;public class AnyClass {public static void main(String[] args) {// 定义ArrayList容器,设置容器内的值类型为IntegerArrayList<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));}}
}

输出:

 

2、泛型的高级用法

(1)限制泛型可用类型

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

class类名称<T extends anyClass>

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

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

例:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LimitClass<T extends List>{public static void mian(String[] args) {// 可实例化已经实现List接口的类LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();// 错误,因为HashMap没实现List()接口// LimitClass<HashMap> l3 = new LimitClass<HashMap>();}
}

(2)使用类型通配符

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

使用泛型类型通配符的语法如下:

泛型类名称<? extends List> anll;

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

例:

A<? extends List> a = null;
a = new A<ArrayList>();
a = new A<LinkedList>();

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

例:

public void doSomething(A<? extends List> a){
}

       如果使用A<?>这种形式实例化泛型类对象,则默认表示可以将A指定为实例化Object及以下的子类类型。

例:

List<String> 11=new ArrayList<String>();	//实例化一个ArrayList对象
I1.add("成员"):	    // 在集合中添加内容
List<?> 12=11;			 // 使用通配符
List<?> l3=new Linkedl ist<Integer>();
System.out.rintn(2.g(0);  // 获取集合中第一个值

       在上例中,List<?>类型的对象可以接受String类型的ArrayList集合,也可以接受Integer类型的LinkedList集合。也许有的读者会有疑问,List<?> 12=11语句与List 12=11存在何种本质区别?这里需要注意的是,使用通配符声明的名称实例化的对象不能对其加入新的信息,只能获取或删除。

例:

l1.set(0,“成员改变");	// 没有使用通配符的对象调用set()方法
// 2.set(0,“成员改变");  // 使用通配符的对象调用set()方法,不能被调用
// 3.set(0, 1);
l2.get(0);              // 可以使用12的实例获取集合中的值
12.remove(0);           // 根据键名删除集合中的值

       注:泛型类型限制除了可以向下限制之外,还可以进行向上限制,只要在定义时使用super 关键字即可。例如,“A<? super List> a=nll;"这样定义后,对象a只接受List接口或上层父类类型,如”a=new A<Objec>;"

(3)继承泛型类与实现泛型接口

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

例:

public class ExtendClass<T1>{class SubClass<T1.T2,T3> extends ExtendClass<T1>{
}

       如果在SubClass类继承ExtendClass类时保留父类的泛型类型,需要在继承时指明,如果没有指明,直接使用extends ExtendsClass语句进行继承操作,则SubClass类中的T1、T2和T3都会自动变为Object,所以在一般情况下都将父类的泛型类型保留。

       定义的泛型接口也可以被实现。

例:

Interface i<T1>{
}
class SubClass2 <T1,T2,T3> implements i<T1>{
}

小结:

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

http://chatgpt.dhexx.cn/article/EyEvIYGJ.shtml

相关文章

【Java系列】深入解析枚举类型

序言 即便平凡的日子仿佛毫无波澜&#xff0c;但在某个特定的时刻&#xff0c;执着的努力便会显现出它的价值和意义。 希望这篇文章能让你不仅有一定的收获&#xff0c;而且可以愉快的学习&#xff0c;如果有什么建议&#xff0c;都可以留言和我交流 问题 思考一下这寄个问题&a…

Java枚举类型(enum)详解

文章目录 理解枚举类型枚举的定义枚举实现原理枚举的常见方法Enum抽象类常见方法编译器生成的Values方法与ValueOf方法 枚举与Class对象枚举的进阶用法向enum类添加方法与自定义构造函数关于覆盖enum类方法enum类中定义抽象方法enum类与接口 枚举与switch枚举与单例模式EnumMap…

java枚举数字_Java枚举类型的使用,数值的二进制表示

一.Java枚举类型的使用 首先请看这段代码: packagejava上课;public classEnumTest {public static voidmain(String[] args) {Size s=Size.SMALL; Size t=Size.LARGE;//s和t引用同一个对象? System.out.println(s==t);//是原始数据类型吗? System.out.println(s.getClass().…

java枚举类型赋值_java枚举类型(转载)

public class TestEnum { /*最普通的枚举*/ public enum ColorSelect { red, green, yellow, blue; } /* 枚举也可以象一般的类一样添加方法和属性,你可以为它添加静态和非静态的属性或方法,这一切都象你在一般的类中做的那样. */ public enum Season { // 枚举列表必须写在最前…

java 枚举类 int_【转】掌握java枚举类型(enum type)

原文网址:http://iaiai.iteye.com/blog/1843553 1 背景 在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量。之前我们通常利用public final static 方法定义的代码如下,分别用1 表示春天,2表示夏天,3表示秋天,4表示冬天。 Java代码 p…

java枚举类型转换_java枚举类型enum值与整数的转换

java编程中偶尔会用到枚举&#xff0c;为了直观&#xff0c;我们通常将枚举值设置为形象的单词&#xff0c;方便理解和使用。枚举类型相当于数据库 中字典表&#xff0c;但是枚举只有字典表的值&#xff0c;缺少其他用来表示和值一一对应的字段&#xff0c;当我们在数据库中保存…

Java中的枚举类型

文章目录 前言一、枚举类简介二、枚举底层原理总结 前言 这里复习一下Java中的枚举类型。实际上&#xff0c;枚举类型是特殊的类&#xff0c;和C语言C中的枚举不太一样&#xff0c;下面我们做详细说明。关于枚举类型有一个单独的设计模式&#xff1a;即单例设计模式。单例类是…

Java枚举类型

目录 一、前言&#xff1a; 二、枚举类型&#xff1a; 三、底层原理 四、应用 应用一&#xff1a;定义常量 底层原理详解 应用二&#xff1a;添加新方法 应用三&#xff1a;与switch结合使用 应用四&#xff1a;实现接口 应用五&#xff1a;使用接口组织枚举 一、前言…

深入理解Java枚举类型(enum)

【版权申明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; http://blog.csdn.net/javazejian/article/details/71333103 出自【zejian的博客】 关联文章&#xff1a; 深入理解Java类型信息(Class对象)与反射…

Python中对基本文件操作

Python中对基本文件操作 一、前言二、创建和打开文件1.打开一个不存在的文件时先创建该文件2.以二进制形式打开文件3.打开文件时指定编码方式 三、关闭文件四、打开文件时使用with语句五、写入文件内容六、读取文件1.读取指定字符2.读取一行3.读取全部行 一、前言 在Python中&a…

C语言——文件操作

文章目录 1. 为什么使用文件2. 什么是文件2.1 程序文件2.2 数据文件2.3 文件名 3. 文件的打开和关闭3.1 文件指针3.2 文件的打开和关闭 4. 文件的顺序读写4.1 fgetc与fputc4.2 fgets与fputs4.3 fscant与fprintf4.3.1 fprintf4.3.2 fscanf 4.4 fread与fwrite4.4.1 fwrite4.4.2 f…

C语言之文件操作

目录 为什么使用文件 文件名 文件指针 流 文件的打开和关闭 前言 文件的打开方式 文件打开关闭函数 fopen函数 fclose函数 文件的顺序读写 fputc函数 fgetc函数 fputs函数 fgets函数 fprintf函数 fscanf函数 fwrite函数 fread函数 文件的随机读写 fseek函…

文件操作(图解)

文件操作 1、文件是什么&#xff1f;1.1 程序文件1.2 数据文件1.3 文件名 2、文件的打开和关闭2.1 文件指针2.2 文件的打开和关闭 3、文件的顺序读写4、文件的随机读写4.1 fseek4.2 ftell4.3 rewind 5、文本文件和二进制文件6、文件读取结束的判定6.1 被错误使用的feof 7、文件…

C++中的文件操作

目录 文件操作C中的文件操作时基于面向对象的C中文件类型分为两种&#xff1a;操作文件的三大类&#xff08;这些类都属于标准模板库&#xff09;:1 文本文件1.1 写文件写文件步骤如下&#xff1a;文件打开方式&#xff1a; 1.2 读文件读取文件数据的四种方式按照喜好记前三个中…

什么是文件操作?为什么要有文件操作?

文章目录 前言一、什么是文件1.1 程序文件1.2 数据文件 二、文件的打开与关闭2.1 文件指针2.2 文件的打开与关闭2.3 文件读写详情表&#xff01;&#xff08;重点&#xff09;2.4 文件的顺序读写&#xff01;&#xff08;重点&#xff09;2.5 文件的随机读写2.5.1 fseek2.5.2 f…

常见文件操作函数

目录 一、文件的打开和关闭 1、文件指针 2、文件打开和关闭 二、文件的顺序读写 1、fgetc()和fputc()函数 2、fgets()和fputs()函数 3、fscanf()和fprintf()函数 4、fread()和fwrite()函数 三、文件的随机读写 1、fseek函数 2、ftell函数 3、rewind函数 四、文本文…

【Linux】Linux的文件操作

文件操作对于不少编程初学者来说都是一件头疼的事情&#xff0c;不管你学习的是什么编程语言&#xff0c;C/C/Java/Go/Python ,因为我们学习到的文件相关的操作对你来说都是一个黑盒&#xff0c;我们只是知道我们应该怎么使用相应的文件函数进行操作&#xff0c;而对于内部的实…

文件操作(详解)

目录 1. 为什么使用文件 2. 什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3. 文件的打开和关闭 3.1 文件指针 ​ 3.2 文件的打开和关闭 4. 文件的顺序读写 4.1 对比一组函数&#xff1a; 5. 文件的随机读写 5.1 fseek 5.2 ftell 5.3 rewind 7. 文件读取结束的…

c语言中的文件操作

目录 引入&#xff1a; 一、文件的打开和关闭 1.文件名 2.文件指针 3.文件的打开和关闭 二、对文件如何操作和流 1.对文件操作相关功能&#xff1a; 2.流 三、文件操作函数(顺序读写) 1."w"输出流&#xff1a; 2."r" 输入流 3."wb"与&…

C语言 文件操作

文件操作在我们的使用中虽然占的不多&#xff0c;但是有些时候&#xff0c;还是需要这部分的知识的。比如&#xff0c;我们做了一个C语言版的售卖系统。现在的想法是在关闭的时候保存这次的结果&#xff0c;然后下一次继续使用&#xff0c;这个时候&#xff0c;就可以使用文件操…