java基礎知識總結7(列舉+泛型)
七、列舉
列舉是一個類型別,是JDK1.5的新特性
列舉的關鍵字是enum
Java中所有的列舉類都是java.lang.Enum的子類
注意:列舉類中可以包含成員有【欄位(常量)、方法(構造方法、普通方法)】
列舉中不能有number;不能賦值————類
只有順序可以比較———–
語法:
enum 列舉名{
列舉體
}
例:
enum Direction{//列舉體
EAST,SOUTH,WEST,NORTH//後面可以有分號也可以沒有
}
呼叫:列舉名.成員
列舉名 name =列舉名.成員;
Direction dir = Direction.EAST;
Enum的方法使用:
Javap—————檢視位元組碼檔案
程式碼:
enum Direction{
EAST(‘e’),SOUTH(’s’),NORTH(‘n’),WEST(‘w’);
protected char a;
private Direction(char a){
this.a = a;
}
public String toString(){
return a+”“;
}
}
位元組碼:
———- javap ———-
Compiled from “Direction.java”
final class Direction extends java.lang.Enum {//不能被例項化
public static final Direction EAST;
public static final Direction SOUTH;
public static final Direction NORTH;
public static final Direction WEST;
protected char a;//預設是private,但可以使用4P
public static Direction[] values();//預設方法,用來遍歷列印列舉成員
public static Direction valueOf(java.lang.String);
public java.lang.String toString();
static {};//靜態初始化塊
}
由上面可以知道列舉繼承java.lang.Enum類,引數的預設修飾符public static final,在列舉中可以使用4p
public enum A{BLUE,RED,BLACK};//宣告並定義一個列舉,初始化為。。。
在一個類中定義一個enum成員,enum預設是靜態的————-相當於類變數
列舉的用法
一、常量
枚舉出來之前都是通過介面
在JDK1.5 之前,我們定義常量都是: public static fianl,現在可以把相關的常量分組到一個列舉型別裡,例:
public enum Color {
RED, GREEN, BLANK, YELLOW
}
二、Switch
JDK1.5之後的switch語句支援Byte,short,int,char,enum型別,使用列舉,能讓我們的程式碼可讀性更強,JDK1.7之後開始支援String型別,例:
enum Signal {
GREEN, YELLOW, RED
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color) {
case RED:
color = Signal.GREEN;
break;
case YELLOW:
color = Signal.RED;
break;
case GREEN:
color = Signal.YELLOW;
break;
}
}
}
三、向列舉中新增新方法
要自定義方法,必須在enum例項序列的最後新增一個分號。而且 Java 要求必須先定義 enum例項,例:
public enum Color {
RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
// 成員變數
private String name;
private int index;
// 構造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
四、覆蓋列舉的方法
例如覆蓋toString()
public enum Color {
RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
// 成員變數
private String name;
private int index;
// 構造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//覆蓋方法
@Override
public String toString() {
return this.index+"_"+this.name;
}
}
五、實現介面
所有的列舉都繼承自java.lang.Enum類。由於Java 不支援多繼承,所以列舉物件不能再繼承其他類,例:
public interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour{
RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
// 成員變數
private String name;
private int index;
// 構造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//介面方法
@Override
public String getInfo() {
return this.name;
}
//介面方法
@Override
public void print() {
System.out.println(this.index+":"+this.name);
}
}
六、使用介面組織列舉
public interface Food {
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}
七、列舉集合
java.util.EnumSet和java.util.EnumMap是兩個列舉集合。EnumSet保證集合中的元素不重複;EnumMap中的key是enum型別,而value則可以是任意型別。
列舉和普通類的區別與聯絡;
1、列舉與類都可以實現多介面;訪問控制符都可以使用(4p),但列舉中預設的是private,類中預設的是package;
2、列舉直接繼承java.lang.Enum類,普通類是繼承java.lang.Object;其中java.long.Enum類實現了java.long.Serializable和java.long.Comparable兩個介面。
3、使用enum定義、非抽象的列舉預設修飾符為public final,因此列舉不能派生子類。
4、列舉的構造器只能使用private訪問控制符,如果省略了列舉的訪問修飾符其預設為private修飾;因為列舉的欄位不能初始化,物件型別的必須呼叫構造方法,所有有多少個成員構造方法就會執行多少次;
5、列舉的所有例項必須在列舉的第一行顯示列出,否則這個列舉永遠都不能生產例項,列出這些例項時系統會自動新增public static final修飾,無需程式設計師顯式新增
6、所有的列舉類都提供了一個values方法,該方法可以很方便的遍歷所有的列舉值
7、關鍵字:列舉是enum,類是class
8、列舉是類型別,類是引用型別
instanceof關鍵字:
public class FX {
public static void main(String[] args) {
boolean b = (“1” instanceof String);//判斷某個物件是不是某個類的例項 Result = Object instanceof Class/interface
//Result:布林型別。
//Object:必選項。任意物件表示式。
//Class:必選項。任意已定義的物件類。
System.out.println(b);
}
}
註解—JDK1.5的新特性
使用位置:類上、方法上、語句上
八、協變與泛型
協變——-可以用在陣列、重寫,不可以用在列舉中
可變引數:
int… a————-代表一個沒有長度限制的陣列———-JDK1.5之後有的
輸入的必須是陣列
Java1.5增加了新特性:可變引數:適用於引數個數不確定,型別確定的情況,java把可變引數當做陣列處理。注意:可變引數必須位於最後一項。只支援有一個可變引數。因為引數個數不定,所以當其後邊還有相同型別引數時,java無法區分傳入的引數屬於前一個可變引數還是後邊的引數,所以只能讓可變引數位於最後一項。
可變引數的特點:
(1)、只能出現在引數列表的最後;
(2)、… 位於變數型別和變數名之間,前後有無空格都可以;
(3)、呼叫可變引數的方法時,編譯器為該可變引數隱含建立一個數組,在方法體中以陣列的形式訪問可變引數。例:
public class Varable {
public static void main(String [] args){
System.out.println(add(2,3));
System.out.println(add(2,3,5));
}
public static int add(int x,int …args){
int sum=x;
for(int i=0;i
協變的作用範圍
1、陣列:如果 A 是 B 的超類,則 A[] 也是 B[] 的超類,所有需要 A[] 的地方都可以用 B[] 代替,例:
public class Test2 {
public static void main(String[] args){
Integer[] ints=new Integer[1];
ints[0]=99;
show(ints);
}
static void show(Number[] ns){
System.out.println(Arrays.toString(ns));
}
}
2、重寫
public class Test2 {
public static void main(String[] args){
P p=new C();
System.out.println(p.get());
}
}
class P{
public Number get(){
return new Integer(0);
}
}
class C extends P{
public Integer get(){
return new Integer(1);
}
}
public class Test2 {
public static void main(String[] args) {
List<Integer> ints = new ArrayList<Integer>();
//incompatible type--型別不相容
show(ints);
}
static void show(List<Number> ns) {
System.out.println(ns);
}
}
泛型(Generic)的本質是型別引數化
————-是JDK1.5提供的新技術,它的本質是型別引數化,類似C++中的模板,它根據應用主要分為泛型方法,泛型介面,泛型類,協變不適用於泛型
泛型————-泛型類class Demo{},泛型介面interface Inter{},泛型方法public T show(T a) {}
泛型的好處是在編譯的時候檢查型別安全,並且所有的強制轉換都是自動和隱式的,提高程式碼的重用率
例1:
public class GenericDemo{
public static void main(String[] args) {
C c1 = new C(new A("aaa"));
C c2 = new C(new B(3.4));//包裝成double---自動裝箱
Object obj = c1.getObj();
A obj = (A)(c1.getObj());//強制轉換
System.out.println(obj);
}
}
class A{
private String x;
public A(String x){
this.x=x;
}
public String getX(){
return x;
}
}
class B{
private Double d;
public B(Double d){
this.d=d ;
}
public Double getD(){
return d;
}
}
class C{
private Object obj;
public C(Object obj){
this.obj=obj ;
}
public Object getObj(){
return obj;
}
}
泛型的使用
一、泛型類:
public class Demo1 {
public static void main(String[] args) {
Generic<String> c = new Generic<String>("asad");
System.out.println(c.getA());
//Generic<int> c1 = new Generic<int>(12);必須要是包裝類
}
}
class Generic{//泛型類
private T a;
public Generic(T a){
this.a = a;
}
public T getA(){
return a;
}
}
二、泛型方法
public static <T> T getX(T t){//泛型方法----------< >--表宣告
return t;
}
三、泛型介面
public class GenericDemo3{
public static void main(String[] args) {
D < int[][]> d = new D< int[][]>();
d.show(new int[][]{{1,4},{2,3}});
}
}
interface IA{
void show(T t);
}
class D implements IA{
public void show(T t){
System.out.println(t.getClass().getName());
}
}
有界型別:
上界:extends 預設上界為Object
Class G < T extends Number,K extends Object,H super Integer>{}
下界:super———-只有萬用字元有下限
extends關鍵字聲明瞭型別的上界,表示引數化的型別可能是所指定的型別,或者是此型別的子類
super關鍵字聲明瞭型別的下界,表示引數化的型別可能是所指定的型別,或者是此型別的父型別,直至Object
規則和限制
1、泛型的型別引數只能是類型別(包括自定義類),不能是簡單型別。
2、同一種泛型可以對應多個版本(因為引數型別是不確定的),不同版本的泛型類例項是不相容的。
3、泛型的型別引數可以有多個。< T,K>
4、泛型的引數型別可以使用extends關鍵字,例如< T extends superclass>。習慣上稱為“有界型別”。
5、泛型的引數型別還可以是萬用字元型別。例如Class< ? > classType = Class.forName(“java.lang.String”)
6、如果只指定了< ? >,而沒有extends,則預設是允許Object及其下的任何Java類了。也就是任意類。
7、萬用字元泛型不但可以向下限制,如< ? extends Collection >,還可以向上限制,如< ? super Double >,表示型別只能接受Double及其上層父類型別,如Number、Object型別的例項。
8、泛型類定義可以有多個泛型引數,中間用逗號隔開,還可以定義泛型介面,泛型方法。這些都與泛型類中泛型的使用規則類似。
一個普通static方法,無法訪問泛型類的型別引數,所以,若普通static方法需要使用泛型引數,必須使其成為泛型方法。