一 Eclipse的使用和程序的斷點調試
錯誤:Bad version number in .class file-編譯器的版本過高,運行環境版本過低(如果編譯器的版本是低的,而運行環境是高的,不會出問題)
解決方案,1 編譯環境變低 2運行環境變高
改變運行環境:工程右鍵,選擇屬性(Properties)選擇java Build Path->Libraries
改變編譯環境:工程右鍵,選擇屬性(Properties)選擇java Compiler
斷點調試
在想要停頓的地方雙擊當前行的最前面
然後Debug As
快捷鍵:F5:跳入(step into)
F6:跳過(step over),跳過當前行代碼
F7:跳出(step return)
觀察變量或表達式的值,點擊變量,選擇Watch
drop to frame 回跳,跳到當前方法的最上面
resume 跳到下一個斷點(如果沒有下一個斷點,則運行完整個程序)
清除所有斷點:Breakpoints視圖
二 eclipse常用快捷鍵
配置快捷鍵
windows->Prefernces->搜索框輸入k->點擊Keys
內容提示:Alt+/
快速修復:Ctrl+1
導包:Ctrl+shift+O
格式化代碼塊:Ctrl+shift+F
向前向後:Alt+方向鍵
添加註釋:Ctrl+shift+/
除去註釋:Ctrl+shift+\
F2:查看方法說明
重置透視圖:windows->Reset Perspective
更改爲大寫:Ctrl+Shift+X
更改爲小寫:Ctrl+Shift+Y
複製行Ctrl+Alt+向下鍵(有些不能用)
查看類的繼承關係:Ctrl+T
查看源代碼
1
2 ctrl +shift+T
Ctrl+Shift+L查看所有快捷鍵
三 junit測試框架
public class Person {
public void run(){
System.out.println("跑");
}
public String eat(){
System.out.println("吃");
return "1";
}
}
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class PersonTest {
Person p;
// 提取測試方法所需要的外界資源
// before after 每個測試方法都運行
// beforeClass afterClass 在類加載的時候運行,只運行一邊
@Before
public void before() {
p = new Person();
}
@BeforeClass
public static void beforeClass() {
System.out.println("beforeClass");
}
@Test
public void testRun() {
p.run();
}
// 釋放外界資源
@After
public void after() {
System.out.println("after");
}
@AfterClass
public static void afterClass() {
System.out.println("afterClass");
}
}
import junit.framework.Assert;
import org.junit.Test;
public class PersonTest1 {
public void testRun() {
Person p=new Person();
p.run();
}
@Test
public void testEat() {
Person p=new Person();
//斷言
//判斷測試是否通過
//Assert.assertEquals("2", p.eat());
Assert.assertEquals(new int []{1,1}, new int[]{1,2});
}
}
四 java5的靜態導入和自動裝箱拆箱
靜態導入用於簡化程序對類靜態屬性和方法的調用
語法:import static 包名.類名.靜態屬性|靜態方法|*
例:import static java.lang.System.out
import static java.lang.Math.*
自動裝箱:指開發人員可以把一個基類數據類型直接賦值給對應的包裝類
自動拆箱:指開發人員可以把一個包裝類對象直接賦值給對應的進本數據類型
典型應用:
List list =new ArrayList();
list.add(1);
int j=(Interger)list.get(0);
五 增強for循環
引入增強for循環的原因,在JDK5以前的版本中,遍歷數組或集合中的元素,需先獲得數組的長度或集合的迭代器,比較麻煩
JDK5中定義了一種新的語法——增強for循環,以簡化此類操作。增強for循環只能用在數組,或實現Iterable接口的集合類上。
語法格式:
for(變量類型 變量 :需迭代的數組或集合){
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Test;
/*
* 增強for
*/
public class StrongFor {
@Test
public void Test1() {
int arr[] = { 1, 2, 3 };
for (int num : arr) {
System.out.println(num);
}
}
@Test
public void Test2() {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
for (Object obj : list) {
int i = (Integer) obj;
System.out.println(i);
}
}
@Test
public void Test3() {
Map map=new HashMap();
map.put("1", "aaa");
map.put("2", "bbb");
map.put("3", "ccc");
//傳統方式1
Set set =map.keySet();
Iterator it=set.iterator();
while (it.hasNext()){
String key= (String) it.next();
String value=(String) map.get(key);
System.out.println(key+"="+value);
}
}
@Test
public void Test4() {
Map map=new LinkedHashMap();//LinkedHashMap()正序。常用語購物車
map.put("1", "aaa");
map.put("2", "bbb");
map.put("3", "ccc");
//傳統方式2
Set set =map.entrySet();
Iterator it=set.iterator();
while (it.hasNext()){
Map.Entry entry=(Entry)it.next();
String key=(String) entry.getKey();
String value=(String) entry.getValue();
System.out.println(key+"="+value);
}
}
@Test
public void Test5() {
Map map=new LinkedHashMap();//LinkedHashMap()正序。常用語購物車
map.put("1", "aaa");
map.put("2", "bbb");
map.put("3", "ccc");
//增強for取Map的第一種方法
for(Object obj:map.keySet()){//把map集合轉換成set集合
String key=(String)obj;
String value =(String) map.get(key);
System.out.println(key+"="+value);
}
}
@Test
public void Test6() {
Map map=new LinkedHashMap();//LinkedHashMap()正序。常用語購物車
map.put("1", "aaa");
map.put("2", "bbb");
map.put("3", "ccc");
//增強for取Map的第二種方法
for(Object obj :map.entrySet()){
Map.Entry entry=(Entry)obj;
String key=(String) entry.getKey();
String value=(String) entry.getValue();
System.out.println(key+"="+value);
}
Set set =map.entrySet();
}
//使用增強for需要注意的幾個問題:增強for只適合取數據,要修改數組或集合中的數據,使用傳統方式
@Test
public void Test7() {
int arr[]={1,2,3};
for(int i:arr){
i=10;
}
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
List list =new ArrayList();
list.add("1");
for(Object obj:list){
obj="10";
}
System.out.println(list.get(0));
}
}
六 可變參數
測試JDK中具有可變參數的類Array.asList().分別傳多個參,傳數組,傳數組又傳參的情況
注意:傳入基本數類型數組的問題
從JDK5開始,java允許爲方法定義長度可變的參數,
語法:public void foo(int...args){
}
注意事項:
調用可變參數的方法時,編譯器將自動創建一個數組保存傳遞給方法的可變參數,因此,程序員可以在方法體中以數組的形式訪問可變參數
可變參數只能處於參數列表的最後,所以一個方法最多只能有一個長度可變的參數。
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
public class ChangeableArgs {
@Test
public void testSum(){
int arr[]={1,2,3,4,5};
sum(arr);
sum(1,2,3,4,5,6);
}
public void sum(int...num){
//可變參數看成數組
int sum=0;
for(int i:num){
sum+=i;
}
System.out.println(sum);
}
@Test
public void testAa(){
aa(1,2,3,4,5);
}
public void aa(int ...nums){
}
@Test
public void bb(){
List list=Arrays.asList("a","b","c");
System.out.println(list);
String arr[]={"1","2","3","4"};
list =Arrays.asList(arr);
System.out.println(list);
//需要的是對象,所以把數組當成了對象,輸出的結果不是預期的
int nums[]={1,2,3}; //把int改成Integer就可以
list=Arrays.asList(nums);
System.out.println(list);
}
}
七 什麼是枚舉類型和定義枚舉
爲什麼需要枚舉?
一些方法在運行時,它需要的數據不能是任意的,而必須是一定範圍內的值,此類問題在JDK5以前採用自定義帶有枚舉功能的類解決,java5以後可以直接使用枚舉予以解決
JDK5新增的enum關鍵字用於定義一個枚舉類
八 定義枚舉的構造函數,方法和字段
package cn.pack;
import org.junit.Test;
public class EnumerationTest {
@Test
public void test(){
print(Grade.B);
}
public void print(Grade g){ //輸出成績A,B,C,D,E
String value =g.getValue();
System.out.println(value);//89-80
}
}
/*class Grade{
private Grade(){
}
public static final Grade A=new Grade();
public static final Grade B=new Grade();
public static final Grade C=new Grade();
public static final Grade D=new Grade();
public static final Grade E=new Grade();
}*/
//==
//如何定義枚舉的構造函數,方法和字段,去封裝更多的信息
enum Grade{ //class A 100-90 B 89-80 C 79-70 D 69-60
A("100-90"),B("89-80"),C("79-70"),D("69-60"),E("59-0");//Object單獨寫A,B,C,D,E;會報錯,因爲沒有了默認的構造函數
private String value;//封裝每個對象對應的分數
//聲明瞭一個有參的構造函數,
private Grade(String value){
this.value=value;
}
public String getValue(){
return this.value;
}
}
九 定義抽象方法的枚舉
import org.junit.Test;
public class AbstractEnumeration {
@Test
public void test() {
print(GradeToo.B);
}
public void print(GradeToo g) { // 輸出成績A,B,C,D,E
String value = g.getValue();
System.out.println(value);// 89-80
}
}
/*
* class Grade{ private Grade(){ } public static final Grade A=new Grade();
* public static final Grade B=new Grade(); public static final Grade C=new
* Grade(); public static final Grade D=new Grade(); public static final Grade
* E=new Grade(); }
*/
// ==
// 如何定義枚舉的構造函數,方法和字段,去封裝更多的信息
enum GradeToo { // class A 100-90 B 89-80 C 79-70 D 69-60
A("100-90") {
public String localeVlaue() {
return "優";
}
},
B("89-80") {
public String localeVlaue() {
return "良";
}
},
C("79-70") {
public String localeVlaue() {
return "一般";
}
},
D("69-60") {
public String localeVlaue() {
return "差";
}
},
E("59-0") {
public String localeVlaue() {
return "不及格";
}
};// Object單獨寫A,B,C,D,E;會報錯,因爲沒有了默認的構造函數
private String value;// 封裝每個對象對應的分數
// 聲明瞭一個有參的構造函數,
private GradeToo(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public abstract String localeVlaue();
}
十 枚舉的常用方法和其它細節
枚舉類具有如下特性:
枚舉類也是一種特殊形式的java類
枚舉類中聲明的每一個枚舉值代表枚舉類的一個實例對象
與java中的普通類一樣,在聲明枚舉類時,也可以聲明屬性,方法和構造函數,但枚舉類的構造函數必須爲私有的(如果爲公有的,別人就可以創建實例了)
枚舉類也可以實現接口,或繼承抽象類
JDK5中擴展了switch語句,他除了可以接收int ,byte,char,short外,它還可以接受一個枚舉類型
若枚舉類型只有一個枚舉值,則可以當作單態設計模式(保存類對象在內存中始終只有一個)使用
java中聲明的枚舉類,均是java.lang.Enum類的孩子,他繼承了Enum類的所有方法,常用方法:
name()
ordinal()
valueof(class enumClass,String name)
values()此方法雖然在JDK文檔中查不到,但每個枚舉類都具有該方法,它用於遍歷枚舉的所有枚舉值
實際開發中,用戶提交的大部分都是String類型,如果用戶提交的數據正確,就能轉換成枚舉
//測試枚舉類的常用方法
@Test
public void test1(){
System.out.println(Grade.C.name());
System.out.println(Grade.C.ordinal());
String str="B";
Grade g=Grade.valueOf(str);
System.out.println(g);
Grade gs[]=Grade.values();
for(Grade g1:gs){
System.out.println(g1);
}
}
十一 反射技術概述
(做框架必須會的技術)
反射就是加載類,並解剖出類的各個組成部分
編程時什麼情況下才需要加載類,並解剖出類的各個組成部分呢?
加載類:
java中有一個Class類用於代表某一個類的字節碼。
Class類既然代表某個類的字節碼,它當然就要提供加載某個類字節碼的方法:forName()。forName方法用於加載某個類的字節碼到內存中,並使用class對象進行封裝
另外兩種得到class對象的方式:類名.class;對象.getClass()
Class對象提供瞭如下常用的方法,這些方法分別用於從類中解剖出構造函數,方法和成員變量(屬性)。解剖出的成員分別使用Constructor,Method,Field對象表示
十二 反射類的構造函數
利用Constructor創建對象
Constructor類提供瞭如下方法,用於創建類的對象:
public Object newInstance(Object...initargs)
initargs 用於指定構造函數接收的參數
package cn.reflec;
import java.util.List;
/*
* 反射,加載類,獲得類的字節碼
*/
public class Person {
/*public static void main(String [] args){
//1
Class clazz=Class.forName("cn/reflec/Person");//加載Person類到內存,返回class對象,保存類的字節碼
//2
Class clazz1=new Person().getClass();
//3
Class clazz2=Person.class;
}*/
public String name="aaaa";
public Person(){
System.out.println("person");
}
public Person(String name){
System.out.println("Person XXXX");
}
public Person(String name,int password){
System.out.println(name+" "+password);
}
private Person (List list){
System.out.println("list");
}
}
package cn.reflec; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; import org.junit.Test; //解剖(反射)類的構造函數,創建類的對象 public class ReflectConstructor { // 反射構造函數:public Person() @Test public void test1() throws Exception { Class clazz = Class.forName("cn.reflec.Person"); Constructor c = clazz.getConstructor(null); Person p = (Person) c.newInstance(null);// 創建實例 System.out.println(p.name); } // 反射構造函數public Person(String name) @Test public void test2() throws Exception { Class clazz = Class.forName("cn.reflec.Person"); Constructor c = clazz.getConstructor(String.class); Person p = (Person) c.newInstance("XXXX");// 創建實例 System.out.println(p.name); } // 反射構造函數 public Person(String name,int password) @Test public void test3() throws Exception { Class clazz = Class.forName("cn.reflec.Person"); Constructor c = clazz.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("XXXX", 13);// 創建實例 System.out.println(p.name); } // 反射構造函數private Person (List list) @Test public void test4() throws Exception { Class clazz = Class.forName("cn.reflec.Person"); Constructor c = clazz.getDeclaredConstructor(List.class); c.setAccessible(true);// 暴力反射 Person p = (Person) c.newInstance(new ArrayList());// 創建實例 System.out.println(p.name); }// 私有的東西不能被外界訪問,但是反射可以做到 @Test //另一種創建對象方法,要求類中必須有一個無參的構造函數 //以下代碼=test1() public void test5() throws Exception { Class clazz = Class.forName("cn.reflec.Person"); Person p=(Person)clazz.newInstance(); System.out.println(p.name); } }
十三 反射類的方法
利用Method執行方法
Method對象提供瞭如下方法,用於執行它所代表的方法:public Object invoke(Object obj,Object...args)
jdk1.4和jdk1.5的invoke方法的區別:
jdk1.5:public Object invoke(Object obj,Object...args)
jdk1.4:public Object invoke(Object obj,Object[]args)
Person類
public void aa1(){
System.out.println("aa1");
}
public void aa1(String name,int password){
System.out.println(name+" "+password);
}
public Class[] aa1(String name,int[] paaword){
return new Class[]{String.class};
}
private void aa1(InputStream in){
System.out.println(in);
}
public static void aa1(int num){
System.out.println(num);
}
package cn.reflec;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import org.junit.Test;
//反射類的方法
public class ReflectMethod {
// 反射類的方法public void aa1()
@Test
public void test1() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Method method = clazz.getMethod("aa1", null);
method.invoke(p, null);// 指定誰的方法跑起來,指定一個對象
}
// 反射類的方法public void aa1(String name,int password){v
@Test
public void test2() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Method method = clazz.getMethod("aa1", String.class, int.class);
method.invoke(p, "ZXX", 38);
}
// 反射類的方法public Class[] aa1(String name,int[] paaword)
@Test
public void test3() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Method method = clazz.getMethod("aa1", String.class, int[].class);
Class cs[] = (Class[]) method.invoke(p, "shuzu", new int[] { 1, 2, 3 });
System.out.println(cs[0]);
}
// 反射類的方法private void aa1(InputStream in)
@Test
public void test4() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Method method = clazz.getDeclaredMethod("aa1", InputStream.class);
method.setAccessible(true);
method.invoke(p, new FileInputStream("c:\\1.txt"));
}
// 反射類的方法private static void aa1(int num)
@Test
public void test5() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Method method = clazz.getMethod("aa1", int.class);
method.invoke(null, 13);// 靜態的方法在調用的時候不用對象
}
}
十四 反射類的main方法
public static void main(String []args){
System.out.println("main!!!");
}
package cn.reflec;
import java.lang.reflect.Method;
import org.junit.Test;
public class reflectMain {
@Test
//利用反射調用一個參數有數組的方法,爲了保存向前(1.5->1.4)兼容
public void test1() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Method method = clazz.getMethod("main", String[].class);
//method.invoke(null, new String[]{"aa","bb"});//main{String s1,String s2}
//method.invoke(null, new Object[]{new String[]{"aa","bb"}});//第一種
method.invoke(null, (Object)new String[]{"aa","bb"});
}
}
十五 反射類的字段
public String name="aaaa";
private int password=123;
private static int age=23;
package cn.reflec;
import java.io.File;
import java.lang.reflect.Field;
import org.junit.Test;
//反射字段
public class ReflectValue {
// 反射public String name="aaaa";
@Test
public void test1() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Field f = clazz.getField("name");
String name = (String) f.get(p);
System.out.println(name);
Object value = f.get(p);// 獲取字段的值
f.set(p, "XXXXXXXXXXXXX");// 設置字段的值
// Class type =f.getType();//在不知道字段的類型的情況下獲取字段的類型
}
// 反射private int password;
@Test
public void test2() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Field f = clazz.getDeclaredField("password");
f.setAccessible(true);
System.out.println(f.get(p));
}
// 反射private static int age=23;
@Test
public void test3() throws Exception {
Person p = new Person();
Class clazz = Class.forName("cn.reflec.Person");
Field f = clazz.getDeclaredField("age");
f.setAccessible(true);
System.out.println(f.get(p));//是靜態方法,但是也需要傳入一個對象進去
}
}
十六 內省操作javabean的屬性
內省(Introspector)
爲什麼要學內省?
開發框架時,經常需要使用java對象的屬性來封裝程序的數據,每次都是用反射技術完成此類操作過於麻煩,所以sun公司開發了一套API,專門用於操作java對象的屬性
什麼是java對象的屬性和屬性的讀寫方法?
內省訪問javaBean屬性的兩種方式:
通過PropertyDescriptor類操作Bean的屬性
通過Instrospecor類獲得Bean對象的BeanInfo,然後通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的getter,setter方法,然後通過反射機制來調用這些方法。
package cn.introspector;
public class PersonJavaBean {//操作 javabean的屬性封裝用戶的數據
//默認有一個繼承自Object的class屬性
// 當字段對外提供了get或set方法時,叫屬性
private String name;// 字段
private String password;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAe(){//也是一個屬性
return null;
}
}
package cn.introspector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import org.junit.Test;
//使用內省api操作bean的屬性
public class ApiOperateBean {
// 得到bean的所有屬性
@Test
public void test1() throws Exception {
BeanInfo info = Introspector.getBeanInfo(PersonJavaBean.class);
// BeanInfo
// info=Introspector.getBeanInfo(PersonJavaBean.class,Object.class);//得到bean自己的屬性,去掉繼承的屬性
PropertyDescriptor[] pds = info.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
System.out.println(pd.getName());
}
}
// 操作bean指定的屬性age
@Test
public void test2() throws Exception {
PersonJavaBean p = new PersonJavaBean();
PropertyDescriptor pd = new PropertyDescriptor("age",
PersonJavaBean.class);
// 得到屬性的寫方法,爲屬性賦值
Method method = pd.getWriteMethod();
method.invoke(p, 28);
System.out.println(p.getAge());
// 獲取屬性的值
method = pd.getReadMethod();
System.out.println(method.invoke(p, null));
}
// 獲取當前操作的屬性的類型
@Test
public void test3() throws Exception {
PersonJavaBean p = new PersonJavaBean();
PropertyDescriptor pd = new PropertyDescriptor("age",
PersonJavaBean.class);
System.out.println(pd.getPropertyType());
}
}
十七 使用beanUtils操縱javabean
package cn.beanutils;
import java.util.Date;
import javax.xml.crypto.Data;
public class PersonJavaBean {//操作 javabean的屬性封裝用戶的數據
//默認有一個繼承自Object的class屬性
// 當字段對外提供了get或set方法時,叫屬性
private String name;// 字段
private String password;
private int age;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAe(){//也是一個屬性
return null;
}
}
package cn.beanutils;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.xml.crypto.Data;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.junit.Test;
//使用beanUtils(第三方)操縱bean的屬性
//第一步,把beanUtils的開發包集成到程序裏來
//本例使用commons-beanutils-1.7.0.jar,commons-logging-1.1.1.jar
public class BeanUtilsTest {
@Test
public void test1() throws IllegalAccessException, InvocationTargetException{
PersonJavaBean p=new PersonJavaBean();
BeanUtils.setProperty(p, "name", "XCC");
System.out.println(p.getName());
}
//這個人的數據由用戶提交,由於在表單裏提交,在服務器接收全是String
@Test
public void test2() throws IllegalAccessException, InvocationTargetException{
String name="name";
String password="123";
String age="34";
String birthday="1995-10-20";
//拿到數據要將其放入對象
PersonJavaBean p=new PersonJavaBean();
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "password", password);
BeanUtils.setProperty(p, "age", age);//自動轉換,只支持8種基本數據類型
//BeanUtils.setProperty(p, "birthday", birthday);//默認不能支持,需要給beanutils註冊轉換器
System.out.println(p.getAge()+p.getName()+p.getPassword());
}
//爲了讓日期賦到beanutils屬性上,我們給beanutils註冊一個日期轉換器
@Test
public void test3() throws IllegalAccessException, InvocationTargetException{
String name="name";
String password="123";
String age="34";
String birthday="1995-10-20";
ConvertUtils.register(new Converter(){//需導入源碼
public Object convert(Class type,Object value){
//使用數據的時候,使用前一定要先檢查
if(value==null){
return null;
}
if(!(value instanceof String)){
//System.out.println("數據類型不對,不轉換");//需要告訴上一層程序
throw new ConversionException("只支持String類型的轉換");
}
String str=(String) value;
if(str.trim().equals("")){
return null;
}
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(str);
} catch (ParseException e) {//出現異常一定報告上一層程序,採用拋出異常的方式
throw new RuntimeException(e);//異常鏈不能斷,需要把原來的異常封裝進去
}
}
}, Date.class);
PersonJavaBean p=new PersonJavaBean();
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "password", password);
BeanUtils.setProperty(p, "age", age);//
BeanUtils.setProperty(p, "birthday", birthday);
Date date =p.getBirthday();
System.out.println(p.getAge()+p.getName()+p.getPassword()+p.getBirthday());
}
//Converter接口中已經寫好了許多轉換器
@Test
public void test4() throws IllegalAccessException, InvocationTargetException{
String name="name";
String password="123";
String age="34";
String birthday="";
ConvertUtils.register(new DateLocaleConverter(),Date.class);//有bug,如果傳入一個空的,如上面的birthday,沒有檢測這種情況
PersonJavaBean p=new PersonJavaBean();
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "password", password);
BeanUtils.setProperty(p, "age", age);//
BeanUtils.setProperty(p, "birthday", birthday);
Date date =p.getBirthday();
System.out.println(p.getAge()+p.getName()+p.getPassword()+p.getBirthday());
}
@Test
public void test5() throws IllegalAccessException, InvocationTargetException{
//用Map封裝
Map map=new HashMap();
map.put("name", "aaa");
map.put("password", "123");
map.put("age", "23");
map.put("birthday", "1995-10-20");
//需要將Map封裝到bean上
ConvertUtils.register(new DateLocaleConverter(),Date.class);//有bug,如果傳入一個空的,如上面的birthday,沒有檢測這種情況
PersonJavaBean bean=new PersonJavaBean();
BeanUtils.populate(bean, map);//用Map集合中的值填充bean的屬性
System.out.println(bean.getAge()+bean.getName()+bean.getPassword()+bean.getBirthday());
}
}
十八 泛型
泛型(Generic)的作用,在JDK5以前,對象保存到集合中就會失去其特性(任何類型傳入,都會變成Object),取出時通常要程序員手工進行類型的強制轉換,這樣不可避免就會引起程序的一些安全性問題,例如:
ArrayList list =new ArrayList();
list.add("abc");
Integer num=(Integer)list.get[0];//運行時會出錯,但編碼時發現不了
JDK5中的泛型允許程序員在編寫集合代碼時,就限制集合的處理類型,從而把原來程序運行時可能發生問題,轉變爲編譯時的問題,以此提高程序的可讀性和穩定性(尤其在大型程序中更爲突出)
示例:
package cn.generic;
import java.util.ArrayList;
import java.util.List;
public class GenericTest {
public static void main(String[]args){
//聲明瞭一個變量,變量指向某一個集合處理類型爲String
List<String> list=new ArrayList<String>();
list.add("aaaaa");
String s=list.get(0);
}
}
掌握泛型的基本應用
掌握泛型集合的存取:
package cn.generic;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
public class Test2 {
@Test
// 帶泛型的集合的存取
public void test1() {
List<String> list = new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
// 傳統
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(value);
}
// 增強for
for (String s : list) {
System.out.println(s);
}
}
@Test
public void test2() {
Map<Integer, String> map = new HashMap<Integer, String>();// Map變量指向的具體的類型必須是對象類型
map.put(1, "aa");
map.put(2, "bb");
map.put(3, "cc");
// 傳統keyset , entryset用的多
Set<Map.Entry<Integer, String>> set = map.entrySet();
Iterator<Map.Entry<Integer, String>> it = set.iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
int key = entry.getKey();// 拆箱
String value = entry.getValue();
System.out.println(key + "=" + value);
}
// 增強for不能對Map迭代,需轉成Set
for (Map.Entry<Integer, String> entry : map.entrySet()) {
int key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
}
}
注意:泛型是提供給javac編譯器使用的,它用於限定集合的輸入類型,讓編譯器在源代碼級別上,即擋住向集合中插入非法數據。但編譯器編譯完帶有泛型的java程序後,生成的class文件中將不帶有泛型信息。以此使程序運行效率不受到影響,這個過程稱之爲“擦除”。
package cn.generic;
import java.util.ArrayList;
public class Test3 {
ArrayList<String> list=new ArrayList<String>();
}
package cn.generic;
import java.util.ArrayList;
public class Test4 {
ArrayList<String> list=new ArrayList();
}
執行後的class文件內容是一樣的用泛型時,如果兩邊都使用泛型,兩邊必須都一樣
但是ArrayList<String> list=new ArrayList();可以,爲了兼容性
ArrayList list=new ArrayList<String>();//也是可以的,否則,現在的程序員調用不了原來的方法
public void bb(){
aa(new ArrayList());//如果上述ArrayList<String> list=new ArrayList();不可以,就無法調用
}
public void aa(ArrayList<String>list){
}
十九 自定義泛型方法和泛型類
java程序中的普通方法,構造方法和靜態方法都可以使用泛型,方法是用泛型前,必須對泛型進行聲明,語法:<T>,T可以是任意字母,但通常必須大寫。<T>通常放在方法的返回值聲明之前:
public static <T>void doxx(T t);
注意:
只有對象類型才能作爲泛型方法的參數
在泛型中可以同時有多個類型
如:public static <K,V> V getValue(K key){return map.get(key);}
package cn.generic;
//自定義帶泛型的方法
public class Test5 {
public void test1(){
a("aaa");
}
public <T> void a(T t){ //以前使用Object,就需要進行強轉,泛型不需要
//傳的什麼類型,返回的就是什麼類型
}
public <T,E> void b(T t,E e){ //使用前需要先聲明
}
}
package cn.generic;
public class Test6<T,E>{//類上面的泛型作用到整個類上,只作用在非靜態成員上
//類裏面的許多方法都使用同一個泛型
public T a(T t){//在類上聲明泛型
return null;
}
public <K>void b(T t,E e,K k){
}
public static <T> void c(T t){//需要自己定義
}
}
兩個例子
package cn.generic;
public class Test7 {
// 編寫一個泛型方法,實現指定位置上的數組元素的交換
public <T> void swap(T arr[], int post1, int post2) {// 將post1和post2交換
T temp = arr[post1];
arr[post1] = arr[post2];
arr[post2] = temp;
}
// 編寫一個泛型方法,接收一個任意數組,並顛倒數組中的所有元素
public <T> void reverse(T arr[]) {
int start = 0;
int end = arr.length - 1;
while (true) {
if (start >= end) {
break;
}
T temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
}