JDK1.5新特性

1、泛型(Generic)

一、概述:
    1)JDK5.0版本之後出現的新特性,用於解決安全問題,是一個類型安全機制。
java

    2)JDK1.5的集合類但願在定義集合時,明確代表你要向集合中裝入那種類型的數據,沒法加入指定類型之外的數據。 程序員

    3)泛型是提供給javac編譯器使用的能夠限定集合中的輸入類型說明的集合時,會去掉「類型」信息,使程序運行效率不受影響,對參數化的泛型類型,getClass()方法的返回值和原始類型徹底同樣。 數組

    4) 沒有使用泛型時,只要是對象,無論是什麼類型的對象,均可以存儲進同一個集合中。使用泛型集合,能夠將一個集合中的元素限定爲一個特定類型,集合中只能存儲同一個類型的對象,這樣更安全;而且當從集合獲取一個對象時,編譯器也能夠知道這個對象的類型,不須要對對象進行強制類型轉換,這樣更方便。泛型就是把原來的類名進行了延長<在JDK 1.5中,你還能夠按原來的方式將各類不一樣類型的數據裝到一個集合中,但編譯器會報告unchecked警告。
Note:
    1)因爲編譯生成的字節碼會去掉泛型的類型信息,只要能跳過編譯器,就能夠往某個泛型集合中加入其它類型的數據,如用反射獲得集合,再調用add方法便可。
    2) 在使用java提供的對象時,何時寫泛型? 緩存

    一般在集合框架中很常見,只要見到<>就要定義泛型。其實<>就是用來接收類型的。當使用集合時,將集合中要存儲的數據類型做爲參數傳遞到<>中便可。 安全

二、格式:

    經過<>來定義要操做的引用數據類型 框架

    如:ArrayList<String> = new ArrayList<String>();     //定義要存入集合中的元素指定爲String類型 eclipse

三、優勢: ide

    a、將運行時期出現的問題ClassCastException,轉移到了編譯時期。方便於程序員解決問題。讓運行時期問題減小、安全。 函數

    b、避免了強制轉換的麻煩。如在實現某一個接口時,指定傳入接口方法的實參的類型的話,在複寫該接口方法時就能夠直接使用指定類型,而不須要強制轉換。 工具

四、術語:

    如:ArrayList<E>類和ArrayList<Integer>

    一、ArrayList<E>整個稱爲泛型類型

    二、ArrayList<E>中的E稱爲類型變量或類型參數

    三、整個ArrayList<Integer>稱爲參數化類型

    四、ArrayList<Integer>中的Integer稱爲類型參數的實例或實際類型參數

    五、ArrayList<Integer>中的<>稱爲typeof

    六、ArrayList稱爲原始類型

    七、參數化:parametered,已經將參數變爲實際類型的狀態。

五、參數化類型的說明:

    1)參數化類型與原始類型的兼容性(原來的方法接受一個集合參數,新類型也要能傳進去

        a、參數化類型可引用一個原始類型的對象,編譯只是報警告。

            如:Collection<String>coll = new Vector();

        b、原始類型可引用一個參數化類型的對象,編譯報告警告

            如:Collectioncoll = new Vector<String>();  

    2)參數的類型不考慮類型參數的繼承關係:

        Vector<String> v = newVector<Objec>();//錯誤的

        Vector<Objec> v = newVector<String>();//錯誤的,不寫Object沒錯,寫了就是明知故犯

    3)編譯器不容許建立泛型變量的數組。即在建立數組實例時,數組的元素不能使用參數化的類型

        如:Vector<Integer>vectorList[] = new Vector<Integer>[10];//錯誤的

六、泛型限定:(用於泛型擴展)
通配符:
    ? 能夠理解爲佔位符。類型不明確時使用,不能使用類型特有方法,例如length()方法。
     T 表明具體類型,能夠接收並操做這個類型。
    ? extends E:  能夠接收 E 類型或者 E 的子類型,上限。
    ? super E: 能夠接收 E 類型或者 E 的父類型,下限。
Note:如下是錯誤的寫法。集合(對象)的泛型的類型左右兩邊要一致。經過上限或者下限來解決。
        ArrayList<Person> al1 = new ArrayList<Student>();
        TreeSet< Student > al = new TreeSet < Person >();
示例以下:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

//動物  父類
class Animal {
	private String name;

	Animal(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}
}

// 貓 繼承父類
class Cat extends Animal {
	Cat(String name) {
		super(name);
	}
}

public class GenericTest {
	public static void main(String[] args) {
		ArrayList<Animal> al = new ArrayList<Animal>();
		al.add(new Animal("abc1"));
		al.add(new Animal("abc2"));
		al.add(new Animal("abc3"));
		printColl(al);// 父類對象的元素集合能夠調用

		ArrayList<Cat> al1 = new ArrayList<Cat>();
		al1.add(new Cat("abc--1"));
		al1.add(new Cat("abc--2"));
		al1.add(new Cat("abc--3"));
		printColl(al1); // 子類對象的元素集合也能夠調用
	}

	// 定義一個上限的泛型方法
	public static void printColl(Collection<? extends Animal> al) {
		Iterator<? extends Animal> it = al.iterator();
		while (it.hasNext()) {
			System.out.println(it.next().getName());
		}
	}
}

七、泛型類

1)若類實例對象中要使用到同一泛型參數,即這些地方引用類型要保持同一個實際類型時,這時候就要採用泛型類型的方式進行定義,也就是類級別的泛型。

2)何時定義泛型類

    當類中要操做的引用數據類型不肯定的時候,早期定義Object來完成擴展。如今定義泛型來完成擴展。

3)泛型類定義的泛型,在整個類中有效。若是被方法使用,那麼泛型類的對象明確要操做的具體類型後,因此要操做的類型就已經固定了。

4)類級別的泛型是根據引用該類名時指定的類型信息來參數化類型變量的,例如,以下兩種方式均可以:

    GenericDao<String>dao = null;

    newgenericDao<String>();

5)語法格式:

       class Utils<TT>{

             private TT s;

             public void settt(TT s){

                 this.s=s;

             }

             public TT getTT(){

                  return s;

             }

        }

Note:

    a、在對泛型進行參數化時,類型參數的實例必須是引用類型,不能是基本類型。

    b、當一個變量被聲明爲參數時,只能被實例變量和方法調用(還有內嵌類型),而不能被靜態變量和靜態方法調用,由於靜態成員是被全部參數化的類共享的。

八、泛型方法

概述:爲了讓不一樣方法能夠操做不一樣類型,並且類型還不肯定,那麼能夠將泛型定義在方法上。其中方法上的泛型能夠不和類泛型相同,靜態方法不能夠訪問類上定義的泛型,但若是靜態方法操做的應用數據類型不肯定,能夠將泛型定義在方法上。

特色:

     1)位置:用於放置泛型的類型參數的<>應出如今方法的其餘全部修飾符以後和在方法的返回類型以前,也就是緊鄰返回值以前,按照慣例,類型參數一般用單個大寫字母表示。

     2)只有引用類型才能做爲泛型方法的實際參數。

     3)除了在應用泛型時可使用extends限定符,在定義泛型時也可使用extends限定符。
        例如:Class.getAnnotation()方法的定義。而且能夠用&來指定多個邊界,如<V extends Serializable& cloneable> void method(){}。 

     4) 普通方法、構造函數和靜態方法中均可以使用泛型。

     5) 能夠用類型變量表示異常,稱之爲參數化的異常,可用於方法的throws列表中,可是不能用於catch子句中。

     6) 在泛型中可同時有多個類型參數,在定義它們的<>中用逗號分開。
        例如:
public static <K,V> V getValue(K key) { return map.get(key);}
示例以下:

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

/*
 * 泛型限制:
 * ? 通配符,能夠理解爲佔位符
 * ?  extends E:  能夠接收 E 類型或者 E 的子類型。上限。
 * ?  super E:  能夠接收 E 類型或者 E 的父類型。下限。
 */
class Person {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	Person(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + "]";
	}

}

class Student extends Person {

	Student(String name) {
		super(name);
	}

	@Override
	public String toString() {
		return "Student [name=" + getName() + "]";
	}

}

public class GenericDemo2 {

	public static void main(String[] args) {
		ArrayList<String> al1 = new ArrayList<String>();
		al1.add("abcd");
		al1.add("efg");
		al1.add("xyz");

		System.out.println("---------printElement1(al1)----------");
		printElement1(al1);
		// printElement2(al2);

		ArrayList<Person> al = new ArrayList<Person>();
		al.add(new Person("zhangsan"));

		al.add(new Student("li"));

		System.out.println("---------printElement1(al)----------");
		printElement1(al);
	}

	public static <T> void printElement1(ArrayList<T> al) {
		Iterator<T> it = al.iterator();
		while (it.hasNext()) {
			T t = it.next();
			t.toString();
			System.out.println(t);
		}
	}

	public static void printElement2(ArrayList<? extends Person> al) {
		Iterator<? extends Person> it = al.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}

}

T和?有什麼區別:

    1)T限定了類型,傳入什麼類型即爲何類型,能夠定義變量,接收賦值的內容。

    2)?爲通配符,也能夠接收任意類型可是不能夠定義變量。

    可是這樣定義,雖然提升了擴展性,可仍是有一個侷限性,就是不能使用其餘類對象的特有方法。通配符方案要比泛型方法更有效,當一個類型變量用來表達兩個參數之間或參數和返回值之間的關係時,即同一個類型變量在方法簽名的兩處被使用,或者類型變量在方法體代碼中也被使用,而不是僅在簽名的時候使用,才須要使用泛型方法。

Note:泛型的定義

    1)定義泛型:當又不肯定的類型須要傳入到集合中,須要定義泛型。

    2)定義泛型類:若是類型肯定後,所操做的方法都是屬於此類型,則定義泛型類。

    3)定義泛型方法:若是定義的方法肯定了,裏面所操做的類型不肯定,則定義泛型方法。

九、類型參數的類型推斷

1)編譯器判斷範型方法的實際類型參數的過程稱爲類型推斷,類型推斷是相對於知覺推斷的,其實現方法是一種很是複雜的過程。

2)根據調用泛型方法時實際傳遞的參數類型或返回值的類型來推斷,具體規則以下:

    a、當某個類型變量只在整個參數列表中的全部參數和返回值中的一處被應用了,那麼根據調用方法時該處的實際應用類型來肯定,這很容易憑着感受推斷出來,即直接根據調用方法時傳遞的參數類型或返回值來決定泛型參數的類型,例如:

       swap(new String[3],3,4)

           ——>    static <E> voidswap(E[] a,int i,int j)

    b、當某個類型變量在整個參數列表中的全部參數和返回值中的多處被應用了,若是調用方法時這多處的實際應用類型都對應同一種類型來肯定,這很容易憑着感受推斷出來,例如:

       add(3,5)

           ——>   static<T> T add(T a,T b)

    c、當某個類型變量在整個參數列表中的全部參數和返回值中的多處被應用了,若是調用方法時這多處的實際應用類型對應到了不一樣的類型,且沒有使用返回值,這時候取多個參數中的最大交集類型,例如,下面語句實際對應的類型就是Number了,編譯沒問題,只是運行時出問題:

       fill(new Integer[3],3.5f)

           ——>    static<T> void fill(T[] a,T v)

    d、當某個類型變量在整個參數列表中的全部參數和返回值中的多處被應用了,若是調用方法時這多處的實際應用類型對應到了不一樣的類型,而且使用返回值,這時候優先考慮返回值的類型,例如,下面語句實際對應的類型就是Integer了,編譯將報告錯誤,將變量x的類型改成float,對比eclipse報告的錯誤提示,接着再將變量x類型改成Number,則沒有了錯誤:

       intx =(3,3.5f)

           ——>   static<T> T add(T a,T b)

    e、參數類型的類型推斷具備傳遞性,下面第一種狀況推斷實際參數類型爲Object,編譯沒有問題,而第二種狀況則根據參數化的Vector類實例將類型變量直接肯定爲String類型,編譯將出現問題:

       copy(newInteger[5],new String[5])

           ——>   static<T> void copy(T[] a,T[]  b);

       copy(newVector<String>(), new Integer[5])

           ——>   static<T> void copy(Collection<T> a ,T[] b);
2、枚舉
一、概述:枚舉是JDK1.5出現的新特性,字面意思理解就是,枚舉中的元素是有限的,能夠一一列舉出來。

二、枚舉的由來:

    問題:要定義星期幾或性別的變量,該怎麼定義?假設用1-7分別表示星期一到星期日,但有人可能會寫成int weekday = 0;或即便使用常量方式也沒法阻止意外。

    解決方案:枚舉就是要讓某個類型的變量的取值只能爲若干個固定值中的一個,不然,編譯器就會報錯。枚舉可讓編譯器在編譯時就能夠控制源程序中填寫的非法值,普通變量的方式在開發階段沒法實現這一目標。
示例:

/*
 * 用普通類如何實現枚舉功能,定義一個Weekday的類來模擬枚舉功能。 
 一、私有的構造方法
 二、每一個元素分別用一個公有的靜態成員變量表示
 三、能夠有若干公有方法或抽象方法。採用抽象方法定義nextDay就將大量的if.else語句轉移成了一個個獨立的類。
 */

abstract class WeekDay {
	private WeekDay() {
	}

	public final static WeekDay SUN = new WeekDay() {
		public WeekDay nextDay() {
			return MON;
		}
	};

	public final static WeekDay MON = new WeekDay() {
		public WeekDay nextDay() {
			return SUN;
		}
	};

	public abstract WeekDay nextDay();

	public String toString() {
		return this == SUN ? "SUM" : "MON";
	}
}

public class WeekDayDemo {

	public static void main(String[] args) {

		// 只能獲取WeekDay中指定的值,不然會出錯
		String today = WeekDay.MON.toString();
		// WeekDay.MON內部實現了WeekDay的nextDay方法,因此有返回值
		String nextDay = WeekDay.MON.nextDay().toString();
		System.out.println("today is " + today + ",nextDay is " + nextDay);
	}
}
Note:

    1)經過enum關鍵字定義枚舉類,枚舉類是一個特殊的class,每一個元素都是該類的一個實例對象。

    2)用枚舉類規定值,如上面的WeekDay類。之後用此類型定義的值只能是這個類中規定好的那些值,若不是這些值,編譯器不會經過。

    3)好處:在編譯時期就會發現錯誤,代表值不符合,減小了運行時期的錯誤。

    4)若是調用者想打印枚舉類中元素的信息,需由編寫此類的人定義toString方法。

三、經常使用方法:

構造器:

    1)構造器只是在構造枚舉值的時候被調用。

    2)構造器只有私有private,毫不容許有public構造器。這樣能夠保證外部代碼沒法從新構造枚舉類的實例

    3)構造器能夠有多個,調用哪一個即初始化相應的值。

非靜態方法:(全部的枚舉類都繼承了Enum方法)

    1)String toString() ;    //返回枚舉量的名稱

    2)int ordinal() ;        //返回枚舉值在枚舉類中的順序,按定義的順序排

    3)Class getClass();      //獲取對應的類名

    4) String name();         //返回此枚舉常量的名稱,在其枚舉聲明中對其進行聲明。

靜態方法:

    1)valueOf(String e) ;    //轉爲對應的枚舉對象,即將字符串轉爲對象

    2)values() ;             //獲取全部的枚舉對象元素
示例以下:

public class EnumDemo {
	public static void main(String[] args) {
		WeekDay weekDay = WeekDay.SUN;
		System.out.println(weekDay);// 輸出枚舉常量名
		System.out.println(weekDay.name());// 輸出對象名
		System.out.println(weekDay.getClass());// 輸出對應類
		System.out.println(weekDay.toString());// 輸出枚舉對象名
		System.out.println(weekDay.ordinal());// 輸出此對象在枚舉常量的次序
		System.out.println(WeekDay.valueOf("WED"));// 將字符串轉化爲枚舉常量
		System.out.println(WeekDay.values().length);// 獲取因此的枚舉元素,並打印其長度
	}
	// 定義枚舉內部類
	public enum WeekDay {
		SUN(1), MON, TUE, WED, THI, FRI, SAT;// 分號無關緊要,但若是下面還有方法或其餘成員時,分號不能省。
		// 並且當有其餘方法時,必須在這些枚舉變量的下方。

		// 無參構造器
		private WeekDay() {
			System.out.println("無參構造器");
		}

		// 有參構造器
		private WeekDay(int day) {
			System.out.println("有參構造器");
		}
	}
}
結果以下:

四、枚舉的高級應用

1)枚舉就至關於一個類,其中也能夠定義構造方法、成員變量、普通方法和抽象方法。

2)枚舉元素必須位於枚舉體中的最開始部分,枚舉元素列表的後要有分號與其餘成員分隔。把枚舉中的成員方法或變量等放在枚舉元素的前面,編譯器報告錯誤。

3)帶構造方法的枚舉

    a、構造方法必須定義成私有的

    b、若是有多個構造方法,該如何選擇哪一個構造方法?

    c、枚舉元素MON和MON()的效果同樣,都是調用默認的構造方法。

4)帶方法的枚舉

示例以下:
/*
 * 抽象的枚舉方法
 * 此時枚舉中的常量須要子類來實現,這是能夠利用內部類的方式來定義枚舉常量
 * 帶方法的枚舉
 1)定義枚舉TrafficLamp
 2)實現普通的next方法
 3)實現抽象的next方法:每一個元素分別是由枚舉類的子類來生成的實例對象,這些子類
 4)用相似內部類的方式進行定義。
 5)增長上表示時間的構造方法
 * */

public class TrafficLampDemo {
	public enum TrafficLamp {
		RED(30) {
			public TrafficLamp nextLamp() {
				return GREEN;
			}
		},
		GREEN(30) {
			public TrafficLamp nextLamp() {
				return YELLOW;
			}
		},
		YELLOW(5) {
			public TrafficLamp nextLamp() {
				return RED;
			}
		};
		private int time;

		// 構造器
		private TrafficLamp(int time) {
			this.time = time;
		}

		// 抽象方法
		public abstract TrafficLamp nextLamp();
	}
}

Note:

    1)匿名內部類比較經常使用

    2)類的方法返回的類型能夠是本類的類型

    3)類中可定義靜態常量,常量的結果就是本身這個類型的實例對象

    4)枚舉只有一個成員時,就能夠做爲一種單例的實現方式
3、註解

一、概述

    1)註解(Annotation)至關於一種標記,在程序中加了註解就等於爲程序打上了某種標記,沒加,則等於沒有某種標記。之後,javac編譯器、開發工具和其餘程序能夠用反射來了解你的類及各類元素上有無何種標記,看你有什麼標記,就去幹相應的事。

    2)標記能夠加在包,類,字段,方法,方法的參數以及局部變量上。

    3)在java.lang包中提供了最基本的註解(annotation)。

    4)格式:@註解類名。

       若是隻有一個value名稱的屬性或其餘屬性缺省,則可@註解名(」屬性值」);

       若是有多個或不缺省或者需從新賦值,則@註解名(屬性名=」屬性值」,…)。

二、java中三種最基本的註解

    1)如@SuppressWarning(」deprecation」):表示壓制過期警告;或者說不要警告過期提示。SupressWarning是告知編譯器或開發工具等不須要再提示指定的警告了;deprecation」是警告的信息,即過期警告。

    2)@Deprecated:表示告知調用者,該成員函數、字段等已通過時,再也不推薦使用。源代碼標記@Deprecated是在JDK1.5中做爲內置的annotation引入的,用於代表類(class)、方法(method)、字段(field)已經再也不推薦使用,而且在之後的JDK版本中可能將其刪除,編譯器在默認狀況下檢測到有此標記的時候會提示警告信息。例如:假定以前的某個類升級了,其中的某個方法已通過時了,不可以將過期的方法刪除,由於可能會影響到以前調用此這個方法的某些程序,這時就能夠經過在方法上加這個註解來標記。

    3)@Override:表示下面的方法是在覆蓋(父類方法),若是不存在覆蓋,就會報錯。加上此註解,可對類中的方法判斷是不是要覆蓋的父類的方法。典型的例子即在類中覆蓋equals(Object obj)方法時,其中的參數類型必須是Object,才能被覆蓋;若不是,則不存在覆蓋。此時若是加上了此註解就會提示警告。

三、註解的應用結構圖

      

Note:註解就至關於一個你的源程序中要調用的一個類,要在源程序中應用某個註解,得先準備好了這個註解類。就像你要調用某個類,得先有開發好這個類。

四、自定義註解及其應用

1)定義格式:@interface名稱{statement}

    如:最簡單的註解類:public @interface MyAnnotation{}

2)元註解(註解的註解)

    即在定義註解類的時候加註解。如兩個經常使用於元註解的註解:Retention和Target

    1)Retetion:用於說明註解保留在哪一個階段(即註解的生命週期)。

    一個註解的生命週期包含:java源程序--(javac)-->class文件--(類加載器)-->內存中的字節碼分別對應Retetion這個枚舉類的值:

        RetetionPolicy.SOURSE:java源文件時期,如@Overried和@SuppressWarning

        RetetionPolicy.CLASS: class文件時期(默認階段)

        RetetionPolicy.RUNTIME:運行時期,如@Deprecated

Note:a)當在源程序上加了註解,javacjava源程序編譯爲class文件時,會對註解的生命週期進行判斷。若是該註解只保留在源程序,則編譯時會將該註解進行相應的處理操做b)class文件中不是字節碼,只有把class文件中的內容加載進內存,用類加載器加載處理後(進行完整的檢查等處理),最終獲得的二進制內容纔是字節碼,

    2)Target:用於說明註解類的使用範圍。如在方法上仍是類上,默認值是任何地方。

    其值可設置爲枚舉類ElementType類中的任何一個,包括:包、字段、方法、方法參數、構造器、類等值。取值爲:

         PACKAGE(包聲明)

         FIELD(字段聲明)

         ANNOTATION_TYPE(註釋類型聲明)

         CONSIRUCTOR(構造器聲明)

         METHOD(方法聲明)

         PARAMETER(參數聲明)

         TYPE(類、接口(包含註釋類型)或枚舉聲明)

         LOCAL_VARIABLE(局部變量聲明)

Note:其中表明類的值是TYPE。由於class、enum、interface和@interface等都是平級的,因此統屬於Type,不可用CLASS表示。

3)註解的應用

    經過反射方式來獲取自定義的註解類,步驟跟註解的應用結構一致。

    如:

       第1、定義註解類:@interfaceA{}

       第2、應用了「註釋類」的類:@A  class B{}

       第3、對「應用註釋類的類」進行反射操做的類:class c{...},操做以下:

             B.class.isAnnotionPresent(A.class);//判斷是否存在此註解類

             A a = B.class.getAnnotation(a.class);//存在的話則獲得這個註釋類的對象 

五、爲註解添加基本屬性

1)屬性:一個註解至關於一個胸牌,但僅經過胸牌還不足以區別帶胸牌的兩我的,這時就須要給胸牌增長一個屬性來區分,如顏色等。

2)定義格式:同接口中的方法同樣:String color();

     定義缺省格式:String value() default 「heima」;

3)應用:直接在註解的括號中添加自身的屬性,如:

    @MyAnnotation(color=」red」)

    1)若是註解中有一個名稱爲value的屬性,且你只想設置value屬性(即其餘屬性都採用默認值或者你只有一個value屬性),那麼能夠省略value=部分,例如:@SuppressWarnings("deprecation")。

    2)能夠爲屬性值指定缺省值(default),應用時一樣能夠從新設置屬性值。

    3)用反射方式得到註解對應的實例對象後,能夠經過該對象調用屬性對應的方法來獲取屬性值。

六、爲註解增長高級屬性

1)能夠爲註解增長的高級屬性的返回值類型有:

    1)八種基本數據類型   

    2)String類型 

    3)Class類型

    4)枚舉類型  

    5)註解類型  

    6)前五種類型的數組

2)數組類型的屬性:

    如:int[]arrayArr() default {1,2,3};//可不定義默認值

    應用:@MyAnnotation(arrayArr={2,3,4}) //可從新賦值

Note:若數組屬性中只有一個元素(或從新賦值爲一個元素),這時屬性值部分可省略大括號。

3)枚舉類型的屬性:

    假設定義了一個枚舉類TrafficLamp,它是EnumTest的內部類,其值是交通燈的三色。

    定義:EnumTest.TrafficLamplamp();

    應用:@MyAnnotation(lamp=EnumTestTrafficLamp.GREEN)

4)註解類型的屬性:

    假定有個註解類:MetaAnnotation,其中定義了一個屬性:String value()

    定義:MetaAnnotation annotation() default @MetaAnnotation(」xxx」);

    應用:@MyAnnotation(annotation=@MetaAnnotation(」yyy」))//從新賦值

能夠認爲上面這個@MyAnnotation是MyAnnotaion類的一個實例對象,一樣的道理,能夠認爲上面這個@MetaAnnotation是MetaAnnotation類的一個實例對象,調用代碼以下:

    MetaAnnotationma =MyAnnotation.annotation();

    System.out.println(ma.value());

5)Class類型的屬性:

    定義:Class cls();

    應用:@MyAnnotation(cls=AnnotationDemo.class)

Note:這裏的.class必須是已定義的類,或是已有的字節碼對象。

6)註解的詳細語法可經過查看java語言規範瞭解即javaLanguage Specification

示例:
package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)//元註釋
@Target({ElementType.METHOD,ElementType.TYPE})//元註解,指定使用範圍
//註解類
public @interface MyAnnotation {
	String color() default "red" ;
	String value();
	//數組
	int[] arr() default {1,2,3};
	//枚舉
	EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.GREEN;
	//註解類
	MetaAnnotation annotation() default @MetaAnnotation("heima");
	//Class類
	Class clazz() default System.class;
}

import java.lang.reflect.Method;

//註解類的應用,給屬性賦值或者從新賦值
@MyAnnotation(lamp=EnumTest.TrafficLamp.YELLOW,value="heima",
			clazz=AnnotationDemo.class,annotation=@MetaAnnotation("itheima"))
//應用類
public class AnnotationDemo {
	@SuppressWarnings("deprecation")//此註解用於抑制過期信息的提示
	@MyAnnotation("Method")//自定義註解應用在方法上
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		
		System.runFinalizersOnExit(true); //這是一個過期了的方法 ,若是沒有註解就會有警告提示
		//判斷此類是否有MyAnnotation註解
		if (AnnotationDemo.class.isAnnotationPresent(MyAnnotation.class)) {
			//若是有,則獲取該註解
			MyAnnotation annotation =AnnotationDemo.class.getAnnotation(MyAnnotation.class);
			System.out.println(annotation);//@cn.itheima.Demo.MyAnnotation()
			System.out.println(annotation.color());//red
			System.out.println(annotation.value());//heima
			System.out.println(annotation.arr().length);//3
			System.out.println(annotation.lamp());//YEllOW
			System.out.println(annotation.annotation().value());//itheima
			System.out.println(annotation.clazz());//class cn.itheima.demo.AnnotationDemo
		}
		
		//獲取方法上的註解
		Method mainMethod=AnnotationDemo.class.getMethod("main",String[].class);
		MyAnnotation annotationMethod=(MyAnnotation) mainMethod.getAnnotation(MetaAnnotation.class);
		SuppressWarnings sw=mainMethod.getAnnotation(SuppressWarnings.class);
		System.out.println(sw);//null
		System.out.println(annotationMethod);//null	
	}
}
4、加強for循環

一、格式:

    for( 數據類型  變量名 : 被遍歷的集合(collection)或者數組 ) { 執行語句 }

二、說明:

    a、對集合進行遍歷。只能獲取集合元素。可是不能對集合進行操做。能夠看做是迭代器的簡寫形式。

    b、迭代器除了遍歷,還能夠進行remove集合中元素的動做。若是使用ListIterator,還能夠在遍歷過程當中對集合進行增刪改查的操做。

三、傳統for循環和高加強or循環的區別:

    高級for有一個侷限性。必須有被遍歷的目標(集合或數組)。

    傳統for遍歷數組時有索引。

Note:
    1)加強for循環所迭代的是集合必須是數組或者是實現了Iterator接口的集合類。
    2)在遍歷數組的時候要使用定義的角標,仍是建議使用傳統for循環。
    3)變量類型前可加修飾符,如final(可被局部內部類訪問到)。

示例:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class ForInhance {

	public static void main(String[] args) {
		// 傳統for與高級for遍歷數組
		String[] arr = { "www", "itheima", "com" };

		for (int x = 0; x < arr.length; x++) {
			System.out.println(arr[x]);
		}
		for (String i : arr) {
			System.out.println("i:" + i);
		}

		// 定義一個HashMap集合
		HashMap<Integer, String> hm = new HashMap<Integer, String>();

		hm.put(1, "www");
		hm.put(2, "itheima");
		hm.put(3, "com");

		// keySet取出方式的高級for遍歷
		Set<Integer> keySet = hm.keySet();
		for (Integer i : keySet) {
			System.out.println(i + "::" + hm.get(i));
		}

		// entrySet取出方式的高級for遍歷
		for (Map.Entry<Integer, String> me : hm.entrySet()) {
			System.out.println(me.getKey() + "------" + me.getValue());
		}
	}
}

5、可變參數

一、概述:若是一個方法在參數列表中傳入多個參數,個數不肯定,那麼每次都要複寫該方法。這時能夠用數組做爲形式參數。可是在傳入時,每次都須要定義一個數組對象,做爲實際參數。在JDK1.5版本開始,就提供了一個新特性:可變參數(VariableParameter)。

二、格式:用"…"這三個點表示,且這三個點位於變量類型和變量名之間,先後有無空格皆可。

Note:
    1) 可變參數其實就是數組參數的簡寫形式,不用每一次都手動的創建數組對象,只要將要操做的元素做爲參數傳遞便可,隱式將這些參數封裝成了數組。
    2) 在使用時注意:可變參數必定要定義在參數列表的最後面。

public class VariableParameterDemo {
	public static void main(String[] args) {
		int retVal = add(108, 109, 110, 111, 112, 113);
		System.out.println("總和爲:" + retVal);
	}

	// ...表明多個參數
	public static int add(int x, int... args) {
		int sum = x;
		// 加強for循環
		for (int arg : args) {
			sum += arg;
		}
		return sum;
	}
}
6、靜態導入

一、寫法:

    import staticjava.util.Arrays.*;    //導入的是Arrays這個類中的因此靜態成員。

    import staticjava.lang.System.*;    //導入了Ssytem類中因此靜態成員。

    沒加static導入的是類,加上static導入的全是某一個類中因此的靜態成員,這樣寫在調用該類的靜態方法時能夠不用再寫類名。如:Arrays.sort(數組);就能夠直接寫sort(數組);

Note:

    1)當導入的兩個類中有同名成員時,須要在成員前加上相應的類名。

    2)當類名重名時,須要指定具體的包名。當方法重名時,指定具體所屬的對象或者類。

示例:
import java.util.*;
import static java.util.Arrays.*;
import static java.lang.System.*;

class StaticImport // extends Object
{
	public static void main(String[] args) {
		out.println("itheima");// 打印輸出時就能夠直接省略書寫System.
		int[] arr = { 3, 1, 5 };

		sort(arr);// 使用Arrays工具類的方法sort時就能夠省略書寫Array.

		int index = binarySearch(arr, 1);// 半分查找也是同樣能夠省略
		out.println("Index=" + index);

		// 當沒有指定繼承時,因此類默認繼承了Object,
		// 由於toString方法都具有,因此爲了區分,必須寫上具體調用者
		out.println(Arrays.toString(arr));
	}
}
7、自動拆箱、自動裝箱
概述:說到這個特性以前得說說包裝類——基本數據類型所定義的應引類型稱爲基本數據類型的包裝類。JDK1.5以前,基本數據類型與包裝類之間的轉換都得依靠指定的方法手動轉換的,而JDK1.5以後,這些操做在使用的時候自動完成,其中包括自動裝箱、自動拆箱。
使用:
    1)自動裝箱:
      eg: Integer num = 1;

    2) 自動裝箱:
      eg: num = num+2;

Note:對於基本數據類型的說明:整數在-128 ~ 127之間的數,包裝成Integer類型對象,會存入常量池中的緩存,再建立一個對象的時候,若是其值在這個範圍內,就會直接到常量池中尋找,由於這些小數值使用的頻率很高,因此緩存到常量池中,被調用時就方便不少。
示例:

public class AutoDemo {

	public static void main(String[] args) {

		// 定義一個Integer類的書numa
		Integer numa = 1;//自定裝箱
		int numc = numa + 1;//自動拆箱
		System.out.println(numc + "---" + numa.getClass().getName());
		// 定義第二個Integer數numb,所賦的值與numa相等
		Integer numb = 1;
		// 判斷numa是否等於numb
		System.out.println("numa == numb\t" + (numa == numb));// true

		// 再的定義a、b,數字相等但都在-127~128範圍外
		Integer a = 128;
		Integer b = 128;
		// 判斷兩個數是否相等
		System.out.println("a == b\t" + (a == b));// false
	}
}
    以上所述即JDK1.5主要的新特性,預知更多新特性可Google詳解,上述僅表明我的觀點,若有出入請諒解。
相關文章
相關標籤/搜索