java EE開發之Servlet第十一課:反射基礎三

新夢想IT發表於2023-04-21

java EE開發之Servlet第十一課:反射基礎三



1 .使用反射機制形成通用sql語句


1)構建insert語句


public static void save(Object obj) {

// 獲取傳遞過來物件的Class類物件

Class c = obj.getClass();

// 獲取資料庫連線

Connection conn = getConn();

// 準備執行SQL語句的物件(車、船)

PreparedStatement pstmt = null;

// 獲取類物件的所有宣告瞭的屬性

Field[] fs = c.getDeclaredFields();

// 解鎖

Field.setAccessible(fs, true);

// 根據獲得的類物件,拼SQL語句

StringBuffer sb = new StringBuffer();

sb.append("insert into ");

// 表名

sb.append(c.getSimpleName());

sb.append(" values( ");

// 拼SQL語句有多少個問號

for (int i = 1; i < fs.length; i++) {

sb.append(" ? ");

if (i < fs.length - 1) {

sb.append(" , ");

}

}

sb.append(" ) ");

try {

// 初始化執行SQL語句的物件

pstmt = conn.prepareStatement(sb.toString());

// 給問號進行賦值

for (int i = 1; i < fs.length; i++) {

pstmt.setObject(i, fs[i].get(obj));

}

// 執行SQL語句

pstmt.executeUpdate();

} catch (SQLException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} finally {

closeAll(conn, pstmt, null);

}

System.out.println(sb);

}



2)構建select語句



public  List<T> queryFX(Class<T> clazz) {

List<T> list = new ArrayList<T>();

// 獲取傳遞過來物件的類物件

//Class c = obj.getClass();

Connection conn = getConn();

PreparedStatement pstmt = null;

ResultSet rs = null;

// 獲取宣告的屬性

Field[] fs = clazz.getDeclaredFields();

// 解鎖

Field.setAccessible(fs, true);


// 拼SQL

StringBuffer sb = new StringBuffer();

sb.append(" select * from tbl_");

sb.append(clazz.getSimpleName());


// 初始化執行SQL語句的物件

try {

pstmt = conn.prepareStatement(sb.toString());

rs = pstmt.executeQuery();


// 從結果集中獲取資料

while (rs.next()) {

// Student stu = new Student();

T o = (T) clazz.newInstance();

// stu.setSid(rs.getInt("sid"));

for (int i = 0; i < fs.length; i++) {

// 獲取rs中的值

Object value = rs.getObject(fs[i].getName());

// 獲value值存入到對應屬性中xxx.setXxx();

if (value instanceof BigDecimal) {

// 將資料中型別為numeric型別的做一個和實體型別對應的轉換

//value = ((BigDecimal) value).doubleValue();

value = ((BigDecimal) value).intValue();

}


/*

* if(value instanceof Timestamp ){ 

*       Timestamp ts =(Timestamp)value; 

*       value = ts.toString(); 

* }

*/


// rs.getObject()獲得的資料型別為時間戳型別

// 需要轉換為實體中對應的java.sql.Date型別時,需要做以下轉換

if (value instanceof Timestamp) {

Timestamp ts = (Timestamp) value;

value = new Date(ts.getTime());

}


// 把值裝入到實體類中屬性中

fs[i].set(o, value);

}

// 將物件放入到list中

list.add(o);

}

} catch (SQLException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} finally {

closeAll(conn, pstmt, rs);

}

return list;

}


注意: 表名和實體類名相同,表的列名和類的屬性名一樣。

總結:利用同樣的思路,可以構建通用刪除,通用更新,讀者自行完成。



2 .克隆


1)普通屬性不需要克隆


2) 淺度克隆:這個類中的屬性沒有引用另外一個型別的物件

該類必須顯示的繼承Object類和實現Cloneable介面,然後重寫clone();就是把我們要克隆的類,實現一個Cloneable的介面,介面中無方法,只是一個標識 而已,然後寫一個方法public void clone();本來是protected的,要改為public 的,這樣才能在非子類中訪問該方法,在main方法中,生成該類的兩個物件,第一個 給他賦值,第二個就讓它等於第一個物件的clone方法,這樣就克隆了,第二個物件的改變不會影響第一個。


public class GrilFriend implements Cloneable {

........

@Override

public Object clone() throws CloneNotSupportedException {

// TODO Auto-generated method stub

return super.clone();

}

}



3)深度克隆:這個類中的屬性有引用另外一個型別的物件

淺克隆,只涉及到一個類的克隆;既然有淺克隆也就有深克隆,深克隆,是指:在第一個類中用到了另外的類作為屬性,那樣的話,當第一個類要克隆,則它所涉及的類則都要標識為克隆的,並實現從clone方法。


@Override

//procted-->public 

public  Object clone() throws CloneNotSupportedException {

//呼叫父類的克隆方法

//稱為淺度克隆

//return super.clone();

//做深度克隆

//把使用者克出來

Users u  = (Users)super.clone();

//把使用者女友克出來

GrilFriend gf= (GrilFriend)u.getGf().clone();


//繫結使用者的克隆的物件和女友有克隆物件

u.setGf(gf);

return u;

}




3.序列化


1)序列化作用:

當我們在電腦上玩遊戲等一些事情時,然而有時我們要去有事,而此時我們退出遊戲,

會有一個是否儲存當前遊戲的按鈕,儲存的是我們當前遊戲的狀態,例如:當前自己的位置,怪物的位置等等。

而這時我們就可以用到序列化來解決這個問題


2)序列化是什麼:

就是指把java生成的一個物件(包括屬性和方法),以一種物件輸出流(ObjectOutputStream)的方式,寫入到硬碟的檔案中(writeObject(Object obj)),以後要使用到這個物件,也可以用物件輸入流(ObjectInputStream)的方式讀到程式中,使用(readObject())把檔案中的內容恢復為一個物件,恢復的物件的資料與當初寫入物件的資料一至,這樣對像就可以在網路中傳輸,以及像遊戲那樣得到自己的位置,怪物的位置等等


3)怎麼實現序列化

(1)需要序列化的類必須實現Serializable,但沒有方法需要實現,它只是一種標示,標示該類可以序列化

(2)建立FileOutputStream,寫到哪個檔案裡,再套用ObjectOutputStream,呼叫writeObject(Object o)序列化物件

(3)建立FileInputStream,讀硬碟的檔案,再套用ObjectInputStream,呼叫readObject()恢復物件

(4)可以同時寫多個物件進去,那麼每個物件都會給它一個標誌位,用來區別,讀的時候先進去先出來,後進去後出來(佇列結構)

(5)static和transient是不能預設序列化,就是指凡是它們修飾的屬性的值不會序列化到檔案裡面去,那麼讀出來也是為空的

(6)可以透過重寫Serializable介面已經註釋的方法

writeObject(ObjectOutputStream out)來序列化static和 transient修飾的屬性的值,透過readObject(ObjectInputStream in),來讀static和 transient修飾的屬性的值這兩個方法必須是private void 的,在序列化物件和讀物件的時候jdk會自動去呼叫這兩個方法,有一些注意事項看程式碼。


完整程式碼



public class Users implements Serializable{

.........

//序列化時,static和transient(瞬時態)修飾的變數,不可序列化

private static String email;

private transient String phone;




序列化



Users users = new Users();

users.setUid(1);

users.setUname("tom");

users.setAge(24);

users.setPhone("13888888");

users.setEmail("aa@qq.com");


try {

//建立物件輸出流

ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("users.txt"));

os.writeObject(users);

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}



反序列化



try {

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users.txt"));

Users users = (Users)ois.readObject();


System.out.println(users.getUid()+"\t"+users.getUname());

System.out.println(users.getPhone()+"\t"+users.getEmail());

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69940641/viewspace-2947475/,如需轉載,請註明出處,否則將追究法律責任。

相關文章