Java枚舉類型與泛型使用解讀
一、枚舉類型
1、使用枚舉類型設置常量
以往設置常量,通常將常量放置在接口中,這樣在程序中就可以直接使用,并且該常量不能被修改,因為在接口中定義常量時,該常量的修飾符為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); // 必須為枚舉中定義的常量 } }
輸出:
注:在上述代碼中,當用戶調用doit()方法時,即使編譯器不接受在接口中定義的常量參數(shù),也不會報錯;但調用doit2()方法, 任意傳遞參數(shù),編譯器就會報錯,因為這個方法只接受枚舉類型的常量作為其參數(shù)。
枚舉類型也可在類的內部進行定義,如:
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()方法返回的結果,正值代表方法中參數(shù)在調用該方法的枚舉對象位置之前; 0代表兩個互相比較的枚舉成員的位置相同;負值代表方法中參數(shù)在調用該方法的枚舉對象位置之后。
例:
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++) { // 將比較結果返回 out.println(c + "與" + Constants2.values()[i] + "的比較結果為:" + c.compareTo(Constants2.values()[i])); } } // 在主方法中調用compare()方法 public static void main(String[] args) { compare(Constants2.valueOf("Constants_B")); } }
輸出:
3、枚舉類型中的構造方法
在枚舉類型中,可以添加構造方法,但是規(guī)定這個構造方法必須為private修飾符所修飾。
枚舉類型定義的構造方法語法如下:
例:
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型的構造方法 private Constants2(String description) { this.description = description; } private Constants2(int i) { // 定義參數(shù)為整型的構造方法 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()方法放置在接口中,使枚舉類型實現(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; }
小結:
- 類型安全。
- 緊湊有效的數(shù)據(jù)定義。
- 可以和程序其他部分完美交互。
- 運行效率高。
二、泛型
在以往的類型轉換時通常有兩種類型,一種是向上轉型操作,如Boolen轉換為Object,另一種是向下轉型操作,如Object轉換為Float。
在這里向上轉型一般是安全的,而如果進行向下轉型操作時用錯了類型,或者并沒有執(zhí)行該操作,就會出現(xiàn)異常,而泛型機制有效地解決了這一問題。
泛型機制語法如下:
類名<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) { // 設置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); // 調用SetT()方法 for (int i = 0; i < a.getT().length; i++) { System.out.println(a.getT()[i]); // 調用getT()方法返回數(shù)組中的值 } } }
輸出:
(3)集合類聲明容器的元素
可以使用K和V兩個字符代表容器中的鍵值和與鍵值相對應的具體值。常用的被泛型化的集合類如下:
由于被泛型化的集合類已經(jīng)是屬于泛型,故不需要再定義泛型類,可直接使用如下所示語句實例化:
例:
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++) { // 根據(jù)容器的長度循環(huán)顯示容器內的值 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++) { // 根據(jù)鍵名獲取鍵值 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 指某個接口或類。
使用泛型限制后,泛型類的類型必須實現(xiàn)或繼承了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) { // 可實例化已經(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)使用類型通配符
在泛型機制中,提供了類型通配符,其主要作用是在創(chuàng)建一個泛型類對象時限制這個泛型類的類型實現(xiàn)或繼承某個接口或類的子類。要聲明這樣一個對象可以使用“?”通配符來表示,同時使用extends關鍵字來對泛型加以限制。
使用泛型類型通配符的語法如下:
泛型類名稱<? extends List> anll;
其中,<? extends List>表示類型未知,當需要使用該泛型對象時,可以單獨實例化。
例:
A<? extends List> a = null; a = new A<ArrayList>(); a = new A<LinkedList>();
除了可以實例化一個限制泛型類型的實例之外,還可以將該實例放置在方法的參數(shù)中。
例:
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存在何種本質區(qū)別?
這里需要注意的是,使用通配符聲明的名稱實例化的對象不能對其加入新的信息,只能獲取或刪除。
例:
l1.set(0,“成員改變"); // 沒有使用通配符的對象調用set()方法 // 2.set(0,“成員改變"); // 使用通配符的對象調用set()方法,不能被調用 // 3.set(0, 1); l2.get(0); // 可以使用12的實例獲取集合中的值 12.remove(0); // 根據(jù)鍵名刪除集合中的值
注:泛型類型限制除了可以向下限制之外,還可以進行向上限制,只要在定義時使用super 關鍵字即可。例如,“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語句進行繼承操作,則SubClass類中的T1、T2和T3都會自動變?yōu)镺bject,所以在一般情況下都將父類的泛型類型保留。
定義的泛型接口也可以被實現(xiàn)。
例:
Interface i<T1>{ } class SubClass2 <T1,T2,T3> implements i<T1>{ }
小結:
- 泛型的類型參數(shù)只能是類類型,不可以是簡單類型,如A<int>這種泛型定義就是錯誤的。
- 泛型的類型個數(shù)可以是多個。
- 可以使用extends 關鍵字限制泛型的類型。
- 可以使用通配符限制泛型的類型。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringBoot @ConfigurationProperties使用詳解
這篇文章主要介紹了SpringBoot @ConfigurationProperties使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02Java?MyBatis是如何執(zhí)行一條SQL語句的
這篇文章主要介紹了Java?MyBatis是如何執(zhí)行一條SQL語句的,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07Java獲取兩個集合List的交集、補集、并集(相加)和差集(相減)的不同方式
這篇文章主要給大家介紹了關于Java獲取兩個集合List的交集、補集、并集(相加)和差集(相減)的不同方式,在一般操作中對于list集合取交集、差集、并集,比較簡單,需要的朋友可以參考下2023-08-08