類加載器:
1.類加載器是將.class的文件加載經內存,也可將普通文件中的信息加載進內存。
2.文件的加載問題:
(1)eclipse會將源程序中的所有.java文件加載成.class文件,以確保編譯,然後放到classPath指定的目錄中去。並且會將非.java文件原封不動的複製到.class指定的目錄中去。在真正編譯的時候,使用classPath目錄中的文件,即放置.class文件的目錄。
(2)寫完程序是要講配置文件放到.class文件目錄中一同打包,這些都是類加載器加載的,資源文件(配置文件)也同樣加載了配置文件。
(3)框架中的配置文件都要放到classPath指定的文件夾中,原因是它的內部就是用類加載器加載的文件。
3.資源文件的加載:是使用類加載器。
(1)由類加載器ClassLoader的一個對象加載經內存,即用getClassLoader()方法加載。若要加載普通文件,可用getResourseAsStream(String name)在classPath的文件中逐一查找要加載的文件。
(2)在.class身上也提供了方法來加載資源文件,其實它內部就是先調用了Loader方法,再加載的資源文件。
如:Reflect.class.getResourseAsStream(String name)
4.配置文件的路徑問題:
(1)用絕對路徑,通過getRealPath()方法運算出來具體的目錄,而不是內部編碼出來的。
一般先得到用戶自定義的總目錄,在加上自己內部的路徑。可以通過getRealPath()方法獲取文件路徑。對配置文件修改是需要要儲存到配置文件中,那麼就要得到它的絕對路徑才行,因此,配置文件要放到程序的內部。
(2)name的路徑問題:
如果配置文件和classPath目錄沒關係,就必須寫上絕對路徑,
如果配置文件和classPath目錄有關係,即在classPath目錄中或在其子目錄中(一般是資源文件夾resource),那麼就得寫相對路徑,因爲它自己瞭解自己屬於哪個包,是相對於當前包而言的。
代碼演示:
配置文件內容:
className=java.util.ArrayList
由內省引出JavaBean
1.內省,是對內部進行檢查,瞭解更多的底層細節。
2.內省的作用:主要針對JavaBean進行操作。
3.JavaBean簡述:
(1)JavaBean是一種特殊的Java類,主要用於傳遞數據信息,這種Java類中的方法主要用於訪問私有的字段,且方法都符合某種特殊的命名規則。
(2)它是一種特殊的Java類,其中的方法名稱等,都符合特殊的規則。只要一個類中含有get和set打頭的方法,就可以將其當做JavaBean使用。
(3)字段和屬性:
字段就是我們定義的一些成員變量,如private String name;等
屬性是具有某些功能,Bean屬性,是含有get或set方法的那些屬性的字段,即這個變量的get屬性,set屬性等。
4.JavaBean的作用:
如果要在兩個模板之間傳遞多個信息,可將這些信息封裝到一個JavaBean中,這種JavaBean的實例對象通常稱之爲值對象(Value Object,簡稱VO),這些信息在類中用私有字段來儲存,如果讀取或設置這些字段的值,則需要通過一些相應的方法來訪問。
5.JavaBean的命名方式
JavaBean的屬性是根據其中的setter和getter方法來確定的,而不是依據其中的變量,如方法名爲setId,則中文意思是設置Id,getId也是如此;去掉前綴,剩餘部分就是屬性名稱,如果剩餘部分的第二個字母小寫,則把剩餘部分改爲小寫。如:getAge/setAge-->age;gettime-->time;setTime-->time;getCPU-->CPU。
6.JavaBean的好處:
(1)在JavaEE開發中,經常要使用JavaBean。很多環境就要求按JavaBean的方式進行操作,別人都這麼用,那麼就必須要求這麼做。
(2)JDK中提供了對JavaBean進行操作的API,這套API稱爲內省,若要自己通過getX的方式來訪問私有x,可用內省這套API,操作JavaBean要比使用普通的方式更方便。
代碼演示:
7.對JavaBean的複雜內省操作:
(1)在IntroSpector類中有getBeanInfo(Class cls)的方法。
(2)獲取Class對象的Bean信息,返回的是BeanInfo類型。
(3)BeanInfo類中有getPropertyDescriptors()的方法,可獲取所有的BeanInfo的屬性信息,返回一個PropertyDescriptor[]。
(4)在通過遍歷的形式,找出與自己想要的那個屬性信息。
BeanUtils工具包
1.BeanUtils等工具包都是由阿帕奇提供的,爲了便於開發。
2.BeanUtils可以將8種基本數據類型進行自動的轉換,因此對於非基本數據類型,就需要註冊轉換器Converter,這就需要ConverUtils包,
3.BeanUtils工具包好處:
(1)提供的set或get方法中,傳入的是字符串,返回的還是字符串,因爲在瀏覽器中,用戶輸入到文本框的都是以字符串的形式發送至服務器上的,所以操作的都是字符串。也就是說這個工具包的內部有自動將整數轉換爲字符串的操作。
(2)支持屬性的級聯操作,即支持屬性鏈。如可以設置:人的腦袋上的眼鏡的眼珠的顏色。這種級聯屬性的屬性連如果自己用反射,那就很困難了,通過這個工具包就可以輕鬆調用。
(3)可以和Map集合進行相互轉換:可將屬性信息通過鍵值對的形式作爲Map集合存儲(通過staticjava.util.Map describe(java.lang.Object bean)的方法),也可以將Map集合轉換爲JavaBean中的屬性信息(通過static voidpopulate(java.lang.Object bean, java.util.Map properties)的方法)。
代碼演示:
1.設置和獲取屬性值:
2.未註冊的屬性值的獲取和設置
3.Map集合在BeanUtils中的應用
1.BeanUtils是以字符串的形式進行操作的
2.PropertyUtils是以傳入值本身的類型進行操作的。
註解
1.註解相當於一種標記,在程序中加了註解就等於爲程序打上了某種標記,沒加,則沒有某種標記。
2.java編譯器、開發工具和其他應用程序就可以用反射來了解自己的類及各種元素上有無何種標記,有什麼標記,就會做出相應的處理。
3.標記可以加在包、類、字段、方法、方法參數,以及局部變量上等等。
4.在java.lang包中提供了最基本的annotation,即註解。
5.格式:@註解類名()。如果有屬性,則在括號中加上屬性名(可省略)和屬性值。
java中三種最基本的註解:
1.@SuppressWarning(”deprecation”)-壓制警告
SupressWarning是告知編譯器或開發工具等提示指定的編譯器警告;
”deprecation”是告知具體的信息即方法已過時。
2.@Deprecated-提示成員等已經過時,不再推薦使用。
源代碼標記@Deprecated是在JDK1.5中作爲內置的annotation引入的,用於表明類(class)、方法(method)、字段(field)已經不再推薦使用,並且在以後的JDK版本中可能將其刪除,編譯器在默認情況下檢測到有此標記的時候會提示警告信息。
例如:假定之前的某個類升級了,其中的某個方法已經過時了,不能夠將過時的方法刪除,因爲可能會影響到調用此類的這個方法的某些程序,這是就可以通過在方法上加這個註解。
3.@Override-提示覆蓋(父類方法)
加上此註解,,可對自己類中的方法判斷是否是要覆蓋的父類的方法,典型的例子即在集合中覆蓋equals(Object obj)方法,其中的參數類型必須是Object,才能被覆蓋,若不是,加上此註解就會提示警告。
註解類
1.定義格式:@interface 名稱{statement}
2.元註解(註解的註解)
一個註解有其生命週期(Retetion)和存放的位置(Taget),這就可以通過元註解說明。
(1)Retetion:用於說明註解保留在哪個時期,加載定義的註解之上。
一個註解的聲明週期包含:
java源程序--(javac)-->class文件--(類加載器)-->內存中的字節碼
第一、當再源程序上加了註解,javac將java源程序編譯爲class文件,可能會把源程序中的一些註解去掉,進行相應的處理操作,當我們拿到源程序的時候,就看不到這些註解了。
第二、假設javac把這些註解留在了源程序中(或者說留在了class文件中),當運行此class文件的時候,用類加載器將class文件調入內存中,此時有轉換的過程,即把class文件中的註解是否保留下來也不一定。
注意:class文件中不是字節碼,只有把class文件中的內部加載進內存,用類加載器加載處理後(進行完整的檢查等處理),最終得到的二進制內容纔是字節碼。
Reteton(枚舉類)取值:
Retetion.Policy.SOURSE:java源文件時期,如@Overried和@SuppressWarning
Retetion.Policy.CLASS: class文件時期(默認階段)
Retetion.Policy.RUNTIME:運行時期,如@Deprecated
(2)Taget:用於說明註解存放在哪些成分上,默認值是任何元素
其值可設置爲枚舉類ElementType類中的任何一個,包括:包、字段、方法、方法參數、構造器、類等值。取值爲:
PACKAGE(包聲明)
FIELD(字段聲明)
ANNOTATION_TYPE(註釋類型聲明)
CONSIRUCTOR(構造器聲明)
METHOD(方法聲明)
PARAMETER(參數聲明)
TYPE(類、接口(包含註釋類型)或枚舉聲明)
LOCAL_VARIABLE(局部變量聲明)
注意:其中代表類的值是TYPE。因爲class、enum、interface和@
interface等都是屬於Type的。不可用CLASS表示.
3.通過反射查看其它類中的註釋:
過程:
第一、註解類:@interfaceA{}
第二、應用了“註釋類”的類:@Aclass B{}
第三、對“應用註釋類的類”進行反射操作的類:class{...},操作如下:
B.class.isAnnotionPresent(A.class);//判斷是否存在此註解類
A a = B.class.getAnnotation(a.class);//存在的話則得到這個註釋類的對象
代碼演示:
爲註解增加基本屬性
1.屬性:一個註解相當於一個胸牌,但僅通過胸牌還不足以區別帶胸牌的兩個人,這時就需要給胸牌增加一個屬性來區分,如顏色等。
2.定義格式:同接口中的方法一樣:String color();定義缺省格式:Stringvalue() default ”ignal”;
3.應用:直接在註解的括號中添加自身的屬性,如:
@ItcastAnnotation(color=”red”)
這個和上面的@SuppressWarnings("deprecation")是一樣的,其中的"deprecation"就是屬性值
1)當只有一個屬性時,可直接傳入屬性值。如”red”
2)當含有其他屬性值的時候,如果那個屬性值是缺省的(default),也可以直接傳入這個屬性值。
爲註解增加高級屬性
1.可以爲註解增加的高級屬性的返回值類型有:
1)八種基本數據類型 2)String類型 3)Class類型
4)枚舉類型 5)註解類型 6)前五種類型的數組
2.數組類型的屬性:
定義:int[]arrayArr() default {1,2,3}; -->可不定義默認值
應用:@MyAnnotation(arrayArr={2,3,4}) --> 可重新賦值
注:若數組屬性中只有一個元素(或重新賦值爲一個元素),這時屬性值部分可省略大括號。
3.枚舉類型的屬性:
假設定義了一個枚舉類TraffLamp,它是EnumTest的內部類,其值是交通燈的三色。
定義:EnumTest.TrafficLamplamp();
應用:@MyAnnotation(lamp=EnumTestTrafficLamp.GREEN)
4.註解類型的屬性:
假定有個註解類:MetaAnnotation,其中定義了一個屬性:String value()
定義:MetaAnnotationannotation() default @MetaAnnotation(”xxx”);
應用:@MyAnnotation(annotation=@MetaAnnotation(”yyy”)) --> 可重新賦值
可認爲上面的@MetaAnnotation是MyAnnotation類的一個實例對象,同樣可以認爲上面的@MetaAnnotation是MetaAnnotation類的一個實例對象,調用:
MetaAnnotation ma =MyAnnotation.annotation();
System.out.println(ma.value());
5.Class類型的屬性:
定義:Class cls();
應用:@MyAnnotation(cls=ItcastAnnotion.class)
注:這裏的.class必須是已定義的類,或是已有的字節碼對象
6.基本數據類型的屬性(以int爲例):
定義:int val()default 3; -->可不定義默認值
應用:@MyAnnotation(val=7) --> 可重新賦值
代碼演示:
1.類加載器是將.class的文件加載經內存,也可將普通文件中的信息加載進內存。
2.文件的加載問題:
(1)eclipse會將源程序中的所有.java文件加載成.class文件,以確保編譯,然後放到classPath指定的目錄中去。並且會將非.java文件原封不動的複製到.class指定的目錄中去。在真正編譯的時候,使用classPath目錄中的文件,即放置.class文件的目錄。
(2)寫完程序是要講配置文件放到.class文件目錄中一同打包,這些都是類加載器加載的,資源文件(配置文件)也同樣加載了配置文件。
(3)框架中的配置文件都要放到classPath指定的文件夾中,原因是它的內部就是用類加載器加載的文件。
3.資源文件的加載:是使用類加載器。
(1)由類加載器ClassLoader的一個對象加載經內存,即用getClassLoader()方法加載。若要加載普通文件,可用getResourseAsStream(String name)在classPath的文件中逐一查找要加載的文件。
(2)在.class身上也提供了方法來加載資源文件,其實它內部就是先調用了Loader方法,再加載的資源文件。
如:Reflect.class.getResourseAsStream(String name)
4.配置文件的路徑問題:
(1)用絕對路徑,通過getRealPath()方法運算出來具體的目錄,而不是內部編碼出來的。
一般先得到用戶自定義的總目錄,在加上自己內部的路徑。可以通過getRealPath()方法獲取文件路徑。對配置文件修改是需要要儲存到配置文件中,那麼就要得到它的絕對路徑才行,因此,配置文件要放到程序的內部。
(2)name的路徑問題:
如果配置文件和classPath目錄沒關係,就必須寫上絕對路徑,
如果配置文件和classPath目錄有關係,即在classPath目錄中或在其子目錄中(一般是資源文件夾resource),那麼就得寫相對路徑,因爲它自己瞭解自己屬於哪個包,是相對於當前包而言的。
代碼演示:
配置文件內容:
className=java.util.ArrayList
public class ReflectTest2 {
public static void main(String [] args)throws Exception{
//讀取系統文件到讀取流中
//方式一:
//InputStream ips = new FileInputStream("config.propert");
/*getRealPath()--得到完整的路徑//如:金山詞霸/內部
* 一定要用完整的路徑,但完整的路徑不是硬編碼出來的,而是運算出來的。*/
//方式二:
//InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/text1/config.propert");
//方式三:
//第一種:配置文件(資源文件)在當前包中
InputStream ips = ReflectTest2.class.getResourceAsStream("resourse/config.propert");
//第二種:配置文件(資源文件)不在當前包中,和此包沒太大關係
//InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/test2/resourse/config.properties");
//加載文件中的鍵值對
Properties props = new Properties();
props.load(ips);
//關閉資源,即ips調用的那個系統資源
//注意:關閉的是ips操作的流,加載進內存後,就不再需要流資源了,需要關閉
ips.close();
//定義變量,將文件中的類名賦值給變量
String className = props.getProperty("className");
//通過變量,創建給定類的對象
Collection cons =
(Collection)Class.forName(className).newInstance();
//將元素添加到集合中
/*Collection cons = new HashSet();*/
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
cons.add(pt1);
cons.add(pt2);
cons.add(pt3);
cons.add(pt1);
//移除元素
cons.remove(pt1);
System.out.println(cons.size());
}
}
由內省引出JavaBean
1.內省,是對內部進行檢查,瞭解更多的底層細節。
2.內省的作用:主要針對JavaBean進行操作。
3.JavaBean簡述:
(1)JavaBean是一種特殊的Java類,主要用於傳遞數據信息,這種Java類中的方法主要用於訪問私有的字段,且方法都符合某種特殊的命名規則。
(2)它是一種特殊的Java類,其中的方法名稱等,都符合特殊的規則。只要一個類中含有get和set打頭的方法,就可以將其當做JavaBean使用。
(3)字段和屬性:
字段就是我們定義的一些成員變量,如private String name;等
屬性是具有某些功能,Bean屬性,是含有get或set方法的那些屬性的字段,即這個變量的get屬性,set屬性等。
4.JavaBean的作用:
如果要在兩個模板之間傳遞多個信息,可將這些信息封裝到一個JavaBean中,這種JavaBean的實例對象通常稱之爲值對象(Value Object,簡稱VO),這些信息在類中用私有字段來儲存,如果讀取或設置這些字段的值,則需要通過一些相應的方法來訪問。
5.JavaBean的命名方式
JavaBean的屬性是根據其中的setter和getter方法來確定的,而不是依據其中的變量,如方法名爲setId,則中文意思是設置Id,getId也是如此;去掉前綴,剩餘部分就是屬性名稱,如果剩餘部分的第二個字母小寫,則把剩餘部分改爲小寫。如:getAge/setAge-->age;gettime-->time;setTime-->time;getCPU-->CPU。
6.JavaBean的好處:
(1)在JavaEE開發中,經常要使用JavaBean。很多環境就要求按JavaBean的方式進行操作,別人都這麼用,那麼就必須要求這麼做。
(2)JDK中提供了對JavaBean進行操作的API,這套API稱爲內省,若要自己通過getX的方式來訪問私有x,可用內省這套API,操作JavaBean要比使用普通的方式更方便。
代碼演示:
public class IntroSpectorTest {
/**
* @param args
*/
/*
* public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ReflectPoint pt1 = new ReflectPoint(3,5);
String propertyName = "x";
//"x"-->"X"-->"getX"-->MethodGetX-->
//內省的方式:
//屬性描述符:PropertyDescriptor
//get屬性信息
PropertyDescriptor pd =
new PropertyDescriptor(propertyName,pt1.getClass());
Method methodGetX = pd.getReadMethod();
Object retVal = methodGetX.invoke(pt1);
System.out.println(retVal);
//set屬性信息
Object value = 7;
PropertyDescriptor pd2 =
new PropertyDescriptor(propertyName,pt1.getClass());
Method methodSetX = pd2.getWriteMethod();
methodSetX.invoke(pt1,value);
System.out.println(pt1.getX());
}
*/
//上面的get或set代碼分別通過選中要重構的代碼,通過右擊選重構獲得get和set方法:
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ReflectPoint pt1 = new ReflectPoint(3,5);
String propertyName = "x";
//一般方式:"x"-->"X"-->"getX"-->MethodGetX-->
//內省方式:
//通過get和set方法獲取屬性值
Object retVal = getProperty(pt1, propertyName);
System.out.println(retVal);
Object value = 7;
setProperty(pt1, propertyName, value);
System.out.println(pt1.getX());
}
//設置屬性值的方法 //此處的類型爲Object,通用,下同
private static void setProperty(Object rf, String propertyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException {
//創建屬性描述符對象,將屬性名稱和加載文件等信息寫入其中
PropertyDescriptor pd =
new PropertyDescriptor(propertyName,rf.getClass());
//通過反射的方法類Method,獲取屬性所對應的set方法
Method methodSetX = pd.getWriteMethod();
methodSetX.invoke(rf, value);
}
//獲取屬性值的方法
private static Object getProperty(Object rf, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
//創建屬性描述符對象,獲取屬性所對應的名稱和加載文件等信息
PropertyDescriptor pd =
new PropertyDescriptor(propertyName,rf.getClass());
//通過反射的方法類Method,獲取屬性所對應的get方法
Method methodGetX = pd.getReadMethod();
Object retVal = methodGetX.invoke(rf);
return retVal;
}
}
7.對JavaBean的複雜內省操作:
(1)在IntroSpector類中有getBeanInfo(Class cls)的方法。
(2)獲取Class對象的Bean信息,返回的是BeanInfo類型。
(3)BeanInfo類中有getPropertyDescriptors()的方法,可獲取所有的BeanInfo的屬性信息,返回一個PropertyDescriptor[]。
(4)在通過遍歷的形式,找出與自己想要的那個屬性信息。
BeanUtils工具包
1.BeanUtils等工具包都是由阿帕奇提供的,爲了便於開發。
2.BeanUtils可以將8種基本數據類型進行自動的轉換,因此對於非基本數據類型,就需要註冊轉換器Converter,這就需要ConverUtils包,
3.BeanUtils工具包好處:
(1)提供的set或get方法中,傳入的是字符串,返回的還是字符串,因爲在瀏覽器中,用戶輸入到文本框的都是以字符串的形式發送至服務器上的,所以操作的都是字符串。也就是說這個工具包的內部有自動將整數轉換爲字符串的操作。
(2)支持屬性的級聯操作,即支持屬性鏈。如可以設置:人的腦袋上的眼鏡的眼珠的顏色。這種級聯屬性的屬性連如果自己用反射,那就很困難了,通過這個工具包就可以輕鬆調用。
(3)可以和Map集合進行相互轉換:可將屬性信息通過鍵值對的形式作爲Map集合存儲(通過staticjava.util.Map describe(java.lang.Object bean)的方法),也可以將Map集合轉換爲JavaBean中的屬性信息(通過static voidpopulate(java.lang.Object bean, java.util.Map properties)的方法)。
代碼演示:
1.設置和獲取屬性值:
public class BeanUtilDemo {
/**
* BeanUtils使用
*/
@Test
public void test1() throws Exception{
//創建對象,設置屬性值
Person p = new Person();
BeanUtils.setProperty(p, "name", "zzz");
String name = BeanUtils.getProperty(p, "name");
System.out.println(name);
}
@Test
public void test2() throws Exception{
//創建對象,傳入屬性值
Person p = new Person();
String name = "wangwu";
String age = "23";
String hight = "173.5";
//設置屬性值
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age);
BeanUtils.setProperty(p, "hight", hight);
//獲取屬性值
System.out.println(BeanUtils.getProperty(p, "name"));
System.out.println(BeanUtils.getProperty(p, "age"));
System.out.println(BeanUtils.getProperty(p, "hight"));
}
2.未註冊的屬性值的獲取和設置
//獲取未註冊的屬性,即非八種基本數據類型的引用類型
//private Date birthday
@Test
public void test3() throws Exception{
Person p = new Person();
String name = "wangwu";
String age = "23";
String hight = "173.5";
String birthday = "1990-09-09";
ConvertUtils.register(new Converter() {
//註冊器Converter接口中方法的重寫
@Override
public Object convert(Class type, Object value) {
if(value == null)
return null;
if(!(value instanceof String))
throw new ConversionException("只支持String類型的轉換");
String str = (String) value;
if(value.equals(""))
return null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try{
return sdf.parse(str);
}catch(ParseException e){
throw new RuntimeException(e);//異常鏈不能掉,這裏必須寫上e
}
}},
Date.class);
//測試
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age);
BeanUtils.setProperty(p, "hight", hight);
BeanUtils.setProperty(p, "birthday", birthday);
System.out.println(BeanUtils.getProperty(p, "name"));
System.out.println(BeanUtils.getProperty(p, "age"));
System.out.println(BeanUtils.getProperty(p, "hight"));
System.out.println(BeanUtils.getProperty(p, "birthday"));
}
//使用已經寫好的註冊器DateLocaleConverter
@Test
public void test4() throws Exception{
Person p = new Person();
String name = "wangwu";
String age = "23";
String hight = "173.5";
String birthday = "1990-09-09";
//將日期註冊到BeanUtils上
ConvertUtils.register(new DateLocaleConverter(), Date.class);//提供的註冊器不健壯,因爲傳入空字符串,就會報錯
//所以,當沒有提供註冊器或需要加強註冊器的時候,可以自己寫
//測試
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age);
BeanUtils.setProperty(p, "hight", hight);
BeanUtils.setProperty(p, "birthday", birthday);
System.out.println(BeanUtils.getProperty(p, "name"));
System.out.println(BeanUtils.getProperty(p, "age"));
System.out.println(BeanUtils.getProperty(p, "hight"));
System.out.println(BeanUtils.getProperty(p, "birthday"));
Date date = p.getBirthday();
System.out.println(date.toLocaleString());
}
3.Map集合在BeanUtils中的應用
@Test
public void test5() throws Exception {
/*
* JDK 7.0新特性:
* Map map = {"name" : "zs", "age" : 22, "hight" : 176.5};
*/
//將數據存入集合
Map map = new TreeMap();
map.put("name", "zhangsan");
map.put("age", "20");
map.put("hight", "172.5");
map.put("birthday", "1999-10-02");
//註冊器
ConvertUtils.register(new DateLocaleConverter(), Date.class);
//獲取屬性
Person p = new Person();
BeanUtils.populate(p, map);
System.out.println(BeanUtils.getProperty(p, "name"));
System.out.println(BeanUtils.getProperty(p, "age"));
System.out.println(BeanUtils.getProperty(p, "hight"));
System.out.println(BeanUtils.getProperty(p, "birthday"));
}
//屬性鏈
@Test
public void test6() throws Exception {
Person p = new Person();
BeanUtils.setProperty(p, "birthday.time", "111212");
System.out.println(BeanUtils.getProperty(p, "birthday.time"));
}
補充:1.BeanUtils是以字符串的形式進行操作的
2.PropertyUtils是以傳入值本身的類型進行操作的。
//PropertyUtils可直接解析爲指定類型,而BeanUtils只能指定字符串的類型
@Test
public void test7() throws Exception {
Person p = new Person();
System.out.println("-----BeanUtiles-------");
BeanUtils.setProperty(p, "age", "22");//字符串形式
System.out.println(BeanUtils.getProperty(p, "age"));
System.out.println(BeanUtils.getProperty(p, "age").getClass().getName());
System.out.println("-----PropertyUtiles-------");
PropertyUtils.setProperty(p, "age", 22);//Integer形式
System.out.println(PropertyUtils.getProperty(p, "age"));
System.out.println(PropertyUtils.getProperty(p, "age").getClass().getName());
}
註解
1.註解相當於一種標記,在程序中加了註解就等於爲程序打上了某種標記,沒加,則沒有某種標記。
2.java編譯器、開發工具和其他應用程序就可以用反射來了解自己的類及各種元素上有無何種標記,有什麼標記,就會做出相應的處理。
3.標記可以加在包、類、字段、方法、方法參數,以及局部變量上等等。
4.在java.lang包中提供了最基本的annotation,即註解。
5.格式:@註解類名()。如果有屬性,則在括號中加上屬性名(可省略)和屬性值。
java中三種最基本的註解:
1.@SuppressWarning(”deprecation”)-壓制警告
SupressWarning是告知編譯器或開發工具等提示指定的編譯器警告;
”deprecation”是告知具體的信息即方法已過時。
2.@Deprecated-提示成員等已經過時,不再推薦使用。
源代碼標記@Deprecated是在JDK1.5中作爲內置的annotation引入的,用於表明類(class)、方法(method)、字段(field)已經不再推薦使用,並且在以後的JDK版本中可能將其刪除,編譯器在默認情況下檢測到有此標記的時候會提示警告信息。
例如:假定之前的某個類升級了,其中的某個方法已經過時了,不能夠將過時的方法刪除,因爲可能會影響到調用此類的這個方法的某些程序,這是就可以通過在方法上加這個註解。
3.@Override-提示覆蓋(父類方法)
加上此註解,,可對自己類中的方法判斷是否是要覆蓋的父類的方法,典型的例子即在集合中覆蓋equals(Object obj)方法,其中的參數類型必須是Object,才能被覆蓋,若不是,加上此註解就會提示警告。
註解類
1.定義格式:@interface 名稱{statement}
2.元註解(註解的註解)
一個註解有其生命週期(Retetion)和存放的位置(Taget),這就可以通過元註解說明。
(1)Retetion:用於說明註解保留在哪個時期,加載定義的註解之上。
一個註解的聲明週期包含:
java源程序--(javac)-->class文件--(類加載器)-->內存中的字節碼
第一、當再源程序上加了註解,javac將java源程序編譯爲class文件,可能會把源程序中的一些註解去掉,進行相應的處理操作,當我們拿到源程序的時候,就看不到這些註解了。
第二、假設javac把這些註解留在了源程序中(或者說留在了class文件中),當運行此class文件的時候,用類加載器將class文件調入內存中,此時有轉換的過程,即把class文件中的註解是否保留下來也不一定。
注意:class文件中不是字節碼,只有把class文件中的內部加載進內存,用類加載器加載處理後(進行完整的檢查等處理),最終得到的二進制內容纔是字節碼。
Reteton(枚舉類)取值:
Retetion.Policy.SOURSE:java源文件時期,如@Overried和@SuppressWarning
Retetion.Policy.CLASS: class文件時期(默認階段)
Retetion.Policy.RUNTIME:運行時期,如@Deprecated
(2)Taget:用於說明註解存放在哪些成分上,默認值是任何元素
其值可設置爲枚舉類ElementType類中的任何一個,包括:包、字段、方法、方法參數、構造器、類等值。取值爲:
PACKAGE(包聲明)
FIELD(字段聲明)
ANNOTATION_TYPE(註釋類型聲明)
CONSIRUCTOR(構造器聲明)
METHOD(方法聲明)
PARAMETER(參數聲明)
TYPE(類、接口(包含註釋類型)或枚舉聲明)
LOCAL_VARIABLE(局部變量聲明)
注意:其中代表類的值是TYPE。因爲class、enum、interface和@
interface等都是屬於Type的。不可用CLASS表示.
3.通過反射查看其它類中的註釋:
過程:
第一、註解類:@interfaceA{}
第二、應用了“註釋類”的類:@Aclass B{}
第三、對“應用註釋類的類”進行反射操作的類:class{...},操作如下:
B.class.isAnnotionPresent(A.class);//判斷是否存在此註解類
A a = B.class.getAnnotation(a.class);//存在的話則得到這個註釋類的對象
代碼演示:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface ItcastAnnotation {}
@ItcastAnnotation()
public class AnnotionTest {
@SuppressWarnings("deprecation")//表示壓制警告的註解
@ItcastAnnotation()
public static void main(String[] args) {
System.runFinalizersOnExit(true);
//反射方式查看註解
//檢查類上是否有註解
if(AnnotionTest.class.isAnnotationPresent(ItcastAnnotation.class)){
//通過反射獲取到註解
ItcastAnnotation annotation = AnnotionTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);
}
}
爲註解增加基本屬性
1.屬性:一個註解相當於一個胸牌,但僅通過胸牌還不足以區別帶胸牌的兩個人,這時就需要給胸牌增加一個屬性來區分,如顏色等。
2.定義格式:同接口中的方法一樣:String color();定義缺省格式:Stringvalue() default ”ignal”;
3.應用:直接在註解的括號中添加自身的屬性,如:
@ItcastAnnotation(color=”red”)
這個和上面的@SuppressWarnings("deprecation")是一樣的,其中的"deprecation"就是屬性值
1)當只有一個屬性時,可直接傳入屬性值。如”red”
2)當含有其他屬性值的時候,如果那個屬性值是缺省的(default),也可以直接傳入這個屬性值。
爲註解增加高級屬性
1.可以爲註解增加的高級屬性的返回值類型有:
1)八種基本數據類型 2)String類型 3)Class類型
4)枚舉類型 5)註解類型 6)前五種類型的數組
2.數組類型的屬性:
定義:int[]arrayArr() default {1,2,3}; -->可不定義默認值
應用:@MyAnnotation(arrayArr={2,3,4}) --> 可重新賦值
注:若數組屬性中只有一個元素(或重新賦值爲一個元素),這時屬性值部分可省略大括號。
3.枚舉類型的屬性:
假設定義了一個枚舉類TraffLamp,它是EnumTest的內部類,其值是交通燈的三色。
定義:EnumTest.TrafficLamplamp();
應用:@MyAnnotation(lamp=EnumTestTrafficLamp.GREEN)
4.註解類型的屬性:
假定有個註解類:MetaAnnotation,其中定義了一個屬性:String value()
定義:MetaAnnotationannotation() default @MetaAnnotation(”xxx”);
應用:@MyAnnotation(annotation=@MetaAnnotation(”yyy”)) --> 可重新賦值
可認爲上面的@MetaAnnotation是MyAnnotation類的一個實例對象,同樣可以認爲上面的@MetaAnnotation是MetaAnnotation類的一個實例對象,調用:
MetaAnnotation ma =MyAnnotation.annotation();
System.out.println(ma.value());
5.Class類型的屬性:
定義:Class cls();
應用:@MyAnnotation(cls=ItcastAnnotion.class)
注:這裏的.class必須是已定義的類,或是已有的字節碼對象
6.基本數據類型的屬性(以int爲例):
定義:int val()default 3; -->可不定義默認值
應用:@MyAnnotation(val=7) --> 可重新賦值
代碼演示:
//將定義的註解的生命週期設置在運行時期
@Retention(RetentionPolicy.RUNTIME)
//定義註解的放置位置
@Target({ElementType.TYPE,ElementType.METHOD})
//自定義註解
public @interface ItcastAnnotation {
//定義屬性
String str();
int val() default 1;
int[] arr() default {2,3,4};
Class cls() default AnnotionTest.class;
EnumText.TrafficLamp lamp() default EnumText.TrafficLamp.YELLOW;
MetaAnnotation annotation() default @MetaAnnotation("sss");
}
//測試註解類,用反射查看其屬性
package cn.itcast.text2;
import cn.itcast.text1.EnumText;
@ItcastAnnotation(annotation=@MetaAnnotation("anntation"),
Lamp=EnumText.TrafficLamp.RED,
arr=7,val=5,str="String",
cls=ItcastAnnotation.class)
public class AnnotionTest {
@SuppressWarnings("deprecation")//表示壓制警告的註解
@ItcastAnnotation(str = "yyy")//有缺省值可不用寫缺省部分
public static void main(String[] args) {
//反射方式查看註解
//檢查類上是否有註解
if(AnnotionTest.class.isAnnotationPresent(ItcastAnnotation.class)){
//通過反射獲取到註解
ItcastAnnotation annotation = AnnotionTest.class.getAnnotation(ItcastAnnotation.class);
//打印查看屬性值
System.out.println(annotation);
System.out.println(annotation.str());
System.out.println(annotation.val());
System.out.println(annotation.arr().length);
System.out.println(annotation.cls().getName());
System.out.println(annotation.lamp().nextLamp());
System.out.println(annotation.annotation().value());
}
}
}
//定義枚舉類,交通燈
package cn.itcast.text1;
public class EnumText {
public static void main(String[] args) {}
//定義交通燈
public enum TrafficLamp{
//定義3個元素,即此類的子類,覆寫抽象方法
RED(30){
@Override
public TrafficLamp nextLamp() {return GREEN;}},
GREEN(45){
@Override
public TrafficLamp nextLamp() {return YELLOW;}},
YELLOW(5) {
@Override
public TrafficLamp nextLamp() {return RED;}};
private int time;
//構造方法
private TrafficLamp(int time){this.time = time;}
//抽象方法,轉爲下個燈
public abstract TrafficLamp nextLamp();
}
}