Java枚舉類型與泛型使用解讀
一、枚舉類型
1、使用枚舉類型設(shè)置常量
以往設(shè)置常量,通常將常量放置在接口中,這樣在程序中就可以直接使用,并且該常量不能被修改,因為在接口中定義常量時,該常量的修飾符為final與static。
常規(guī)定義常量的代碼如下所示。
例:在接口中定義常量的常規(guī)方式
public interface Constants{
public static final int Constants_A = 1;
public static final int Constants_B = 12;
}枚舉類型出現(xiàn)后,逐漸取代了這種常量定義方式。
使用枚舉類型定義常量的語法如下:
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) { // 定義一個方法,這里的參數(shù)為int型
switch (c) { // 根據(jù)常量的值做不同操作
case Constants.Constants_A:
System.out.println("doit() Constants_A");
break;
case Constants.Constants_B:
System.out.println("doit() Constants_B");
break;
}
}
// 定義一個方法,這里的參數(shù)為枚舉類型對象
public static void doit2(Constants2 c) {
switch (c) { // 根據(jù)枚舉類型對象做不同操作
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); // 必須為枚舉中定義的常量
}
}輸出:

注:在上述代碼中,當(dāng)用戶調(diào)用doit()方法時,即使編譯器不接受在接口中定義的常量參數(shù),也不會報錯;但調(diào)用doit2()方法, 任意傳遞參數(shù),編譯器就會報錯,因為這個方法只接受枚舉類型的常量作為其參數(shù)。
枚舉類型也可在類的內(nèi)部進(jìn)行定義,如:
public class ConstantsTest {
enum Constants2{ /將常放在枚舉類型中
Constants A,
Constants_ B
}
}這種形式類似于內(nèi)部類形式,當(dāng)編譯該類時,除了ConstantsTest.class 外,還存在Constants-Test$1.class 與ConstantsTest$Constants2.class文件。
2、枚舉類型常用方法
用戶可以將一個枚舉類型看作是-一個類,它繼承于java.lang.Enum類,當(dāng)定義-一個枚舉類型時,每一個枚舉類型成員都可以看作是枚舉類型的一個實例,這些枚舉類型成員都默認(rèn)被final、public.static修飾,所以當(dāng)使用枚舉類型成員時直接使用枚舉類型名稱調(diào)用枚舉類型成員即可。
枚舉類型的常用方法如下所示

注:調(diào)用compareTo()方法返回的結(jié)果,正值代表方法中參數(shù)在調(diào)用該方法的枚舉對象位置之前; 0代表兩個互相比較的枚舉成員的位置相同;負(fù)值代表方法中參數(shù)在調(diào)用該方法的枚舉對象位置之后。
例:
import static java.lang.System.*;
public class EnumMethodTest {
enum Constants2 { // 將常量放置在枚舉類型中
Constants_A, Constants_B
}
// 定義比較枚舉類型方法,參數(shù)類型為枚舉類型
public static void compare(Constants2 c) {
// 根據(jù)values()方法返回的數(shù)組做循環(huán)操作
for (int i = 0; i < Constants2.values().length; i++) {
// 將比較結(jié)果返回
out.println(c + "與" + Constants2.values()[i] + "的比較結(jié)果為:"
+ c.compareTo(Constants2.values()[i]));
}
}
// 在主方法中調(diào)用compare()方法
public static void main(String[] args) {
compare(Constants2.valueOf("Constants_B"));
}
}輸出:
![]()
3、枚舉類型中的構(gòu)造方法
在枚舉類型中,可以添加構(gòu)造方法,但是規(guī)定這個構(gòu)造方法必須為private修飾符所修飾。
枚舉類型定義的構(gòu)造方法語法如下:
例:
import static java.lang.System.*;
public class EnumIndexTest {
enum Constants2 { // 將常量放置在枚舉類型中
Constants_A("我是枚舉成員A"), // 定義帶參數(shù)的枚舉類型成員
Constants_B("我是枚舉成員B"), Constants_C("我是枚舉成員C"), Constants_D(3);
private String description;
private int i = 4;
private Constants2() {
}
// 定義參數(shù)為String型的構(gòu)造方法
private Constants2(String description) {
this.description = description;
}
private Constants2(int i) { // 定義參數(shù)為整型的構(gòu)造方法
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] + "調(diào)用getDescription()方法為:"
+ Constants2.values()[i].getDescription());
}
out.println(Constants2.valueOf("Constants_D") + "調(diào)用getI()方法為:"
+ Constants2.valueOf("Constants_D").getI());
}
}輸出:

注:在這里將枚舉類型的構(gòu)造方法設(shè)置為private修飾,以防止客戶代碼實例化一個枚舉類型。
除了可以使用上例中所示的方式定義getDescription()方法獲取枚舉類型成員定義時的描述之外,還可以將這個getDescription()方法放置在接口中,使枚舉類型實現(xiàn)該接口,然后使每個枚舉類型實現(xiàn)接口中的方法。
例:
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;
}小結(jié):
- 類型安全。
- 緊湊有效的數(shù)據(jù)定義。
- 可以和程序其他部分完美交互。
- 運行效率高。
二、泛型
在以往的類型轉(zhuǎn)換時通常有兩種類型,一種是向上轉(zhuǎn)型操作,如Boolen轉(zhuǎn)換為Object,另一種是向下轉(zhuǎn)型操作,如Object轉(zhuǎn)換為Float。
在這里向上轉(zhuǎn)型一般是安全的,而如果進(jìn)行向下轉(zhuǎn)型操作時用錯了類型,或者并沒有執(zhí)行該操作,就會出現(xiàn)異常,而泛型機(jī)制有效地解決了這一問題。
泛型機(jī)制語法如下:
類名<T>
1、泛型的常規(guī)用法
(1)定義泛型時聲明多個類型
MutiOverClass<T1, T2> MutiOverClass:泛型類名稱
(2)定義泛型類型時聲明數(shù)組類型
定義泛型時也可聲明數(shù)組類型,但是要注意不可以使用泛型來建立數(shù)組的實例。
例:
public class ArrayClass<T> {
private T[] array; // 定義泛型數(shù)組
public void SetT(T[] array) { // 設(shè)置SetXXX()方法為成員數(shù)組賦值
this.array = array;
}
public T[] getT() { // 獲取成員數(shù)組
return array;
}
public static void main(String[] args) {
ArrayClass<String> a = new ArrayClass<String>();
String[] array = { "成員1", "成員2", "成員3", "成員4", "成員5" };
a.SetT(array); // 調(diào)用SetT()方法
for (int i = 0; i < a.getT().length; i++) {
System.out.println(a.getT()[i]); // 調(diào)用getT()方法返回數(shù)組中的值
}
}
}輸出:

(3)集合類聲明容器的元素
可以使用K和V兩個字符代表容器中的鍵值和與鍵值相對應(yīng)的具體值。常用的被泛型化的集合類如下:

由于被泛型化的集合類已經(jīng)是屬于泛型,故不需要再定義泛型類,可直接使用如下所示語句實例化:
例:
public Map<K, V> m = new HashMap<K, V>();
例:
import java.util.*;
public class AnyClass {
public static void main(String[] args) {
// 定義ArrayList容器,設(shè)置容器內(nèi)的值類型為Integer
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1); // 為容器添加新值
for (int i = 0; i < a.size(); i++) {
// 根據(jù)容器的長度循環(huán)顯示容器內(nèi)的值
System.out.println("獲取ArrayList容器的值:" + a.get(i));
}
// 定義HashMap容器,設(shè)置容器的鍵名與鍵值類型分別為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++) {
// 根據(jù)鍵名獲取鍵值
System.out.println("獲取Map容器的值" + m.get(i));
}
// 定義Vector容器,使容器中的內(nèi)容為String型
Vector<String> v = new Vector<String>();
for (int i = 0; i < 5; i++) {
v.addElement("成員" + i); // 為Vector容器添加內(nèi)容
}
for (int i = 0; i < v.size(); i++) {
// 顯示容器中的內(nèi)容
System.out.println("獲取Vector容器的值" + v.get(i));
}
}
}輸出:

2、泛型的高級用法
(1)限制泛型可用類型
默認(rèn)可以使用任何類型來實例化一個泛型類對象,但Java中也對泛型類實例的類型作了限制。語法如下:
class類名稱<T extends anyClass>
其中,anyClass 指某個接口或類。
使用泛型限制后,泛型類的類型必須實現(xiàn)或繼承了anyClass這個接口或類。無論anyClass是接口還是類,在進(jìn)行泛型限制時都必須使用extends 關(guān)鍵字。
例:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LimitClass<T extends List>{
public static void mian(String[] args) {
// 可實例化已經(jīng)實現(xiàn)List接口的類
LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();
LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();
// 錯誤,因為HashMap沒實現(xiàn)List()接口
// LimitClass<HashMap> l3 = new LimitClass<HashMap>();
}
}(2)使用類型通配符
在泛型機(jī)制中,提供了類型通配符,其主要作用是在創(chuàng)建一個泛型類對象時限制這個泛型類的類型實現(xiàn)或繼承某個接口或類的子類。要聲明這樣一個對象可以使用“?”通配符來表示,同時使用extends關(guān)鍵字來對泛型加以限制。
使用泛型類型通配符的語法如下:
泛型類名稱<? extends List> anll;
其中,<? extends List>表示類型未知,當(dāng)需要使用該泛型對象時,可以單獨實例化。
例:
A<? extends List> a = null; a = new A<ArrayList>(); a = new A<LinkedList>();
除了可以實例化一個限制泛型類型的實例之外,還可以將該實例放置在方法的參數(shù)中。
例:
public void doSomething(A<? extends List> a){}如果使用A<?>這種形式實例化泛型類對象,則默認(rèn)表示可以將A指定為實例化Object及以下的子類類型。
例:
List<String> 11=new ArrayList<String>(); //實例化一個ArrayList對象
I1.add("成員"): // 在集合中添加內(nèi)容
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存在何種本質(zhì)區(qū)別?
這里需要注意的是,使用通配符聲明的名稱實例化的對象不能對其加入新的信息,只能獲取或刪除。
例:
l1.set(0,“成員改變"); // 沒有使用通配符的對象調(diào)用set()方法 // 2.set(0,“成員改變"); // 使用通配符的對象調(diào)用set()方法,不能被調(diào)用 // 3.set(0, 1); l2.get(0); // 可以使用12的實例獲取集合中的值 12.remove(0); // 根據(jù)鍵名刪除集合中的值
注:泛型類型限制除了可以向下限制之外,還可以進(jìn)行向上限制,只要在定義時使用super 關(guān)鍵字即可。例如,“A<? super List> a=nll;"這樣定義后,對象a只接受List接口或上層父類類型,如”a=new A<Objec>;"
(3)繼承泛型類與實現(xiàn)泛型接口
定義為泛型的類和接口也可被繼承與實現(xiàn)。
例:
public class ExtendClass<T1>{
class SubClass<T1.T2,T3> extends ExtendClass<T1>{
}如果在SubClass類繼承ExtendClass類時保留父類的泛型類型,需要在繼承時指明,如果沒有指明,直接使用extends ExtendsClass語句進(jìn)行繼承操作,則SubClass類中的T1、T2和T3都會自動變?yōu)镺bject,所以在一般情況下都將父類的泛型類型保留。
定義的泛型接口也可以被實現(xiàn)。
例:
Interface i<T1>{
}
class SubClass2 <T1,T2,T3> implements i<T1>{
}小結(jié):
- 泛型的類型參數(shù)只能是類類型,不可以是簡單類型,如A<int>這種泛型定義就是錯誤的。
- 泛型的類型個數(shù)可以是多個。
- 可以使用extends 關(guān)鍵字限制泛型的類型。
- 可以使用通配符限制泛型的類型。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java中MultipartFile和File最簡單的互相轉(zhuǎn)換示例
這篇文章主要給大家介紹了關(guān)于java中MultipartFile和File最簡單的互相轉(zhuǎn)換的相關(guān)資料,MultipartFile和File都是Java中用于處理文件上傳的類,MultipartFile用于處理上傳的文件,File用于處理本地磁盤上的文件,需要的朋友可以參考下2023-09-09
SpringBoot集成Prometheus實現(xiàn)監(jiān)控的過程
這篇文章主要介紹了SpringBoot集成Prometheus實現(xiàn)監(jiān)控,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09
@JsonSerialize(using = LongToStringUtil.class)注解的使
這篇文章主要介紹了@JsonSerialize(using = LongToStringUtil.class)注解的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
淺談byte和長度為8的boolean數(shù)組互相轉(zhuǎn)換
下面小編就為大家?guī)硪黄獪\談byte和長度為8的boolean數(shù)組互相轉(zhuǎn)換。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11
Spring Boot開箱即用可插拔實現(xiàn)過程演練與原理解析
本文通過深入探討Spring Boot的背景歷史、業(yè)務(wù)場景、功能點以及底層原理,并通過Java代碼手寫模擬了Spring Boot的啟動過程和自動配置功能,為開發(fā)者提供了一個全面的理解,感興趣的朋友跟隨小編一起看看吧2024-11-11

