首页 > 编程语言 >java EE开发之Servlet第十一课:反射基础三

java EE开发之Servlet第十一课:反射基础三

时间:2023-04-21 15:15:23浏览次数:32  
标签:java 克隆 EE value 对象 sb 序列化 Servlet users

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("[email protected]");

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();
}

标签:java,克隆,EE,value,对象,sb,序列化,Servlet,users
From: https://www.cnblogs.com/xmxit/p/17340378.html

相关文章

  • JAVA入门第一天随记
    通过狂神第一天的课,对内容进行总结:一、关于markdown语法的学习1.对常用的语法进行总结1.标题2.字体斜体粗体粗斜体3.删除线无序列表2.快捷键Ctrl+Z:撤销Ctrl+X:剪切Ctrl+S:保存win+R:打开运行win+E:打开我的电脑3.打开CMD的方式1.Win+R输入cmd打开控......
  • JAVA获取当前时间的三种方法
    1、java.util.Dateday=newDate();SimpleDateFormatsdf=newSimpleDateFormat(“yyyy-MM-ddHH:mm:ss”);System.out.println(sdf.format(day));通过Date类来获取当前时间,比较常用。需要使用Java.util.Date类,速度一般。2、SimpleDateFormatsdf=newSimpleDateFormat......
  • eeprom保存小数并且读出
    使用野火的eeprom驱动union{floatf;charb[10];}value;//value.f=0.248745;value.f=-248.7921;I2C_EE_BufferWrite(value.b,1,sizeof(value.b));//从地址1开始写入数据union{floatd;chark[10];}value1;......
  • java实现两张图片的相似度
    图片相似度java实现:https://zhuanlan.zhihu.com/p/568827637https://github.com/MingGH/calculate-pic-looklike 前端html5调用摄像头:https://www.cnblogs.com/hss-blog/p/9984878.htmlhttps://jeff_zhong.gitee.io/demo/dist/camera.html需要改正的是:<inputid="file"ty......
  • Java入门教程(1)——Java概述
    文章目录1.编程环境1.1开发环境2.2编程工具2.语言特点3.java的发展历程1.编程环境1.1开发环境JDK称为Java开发包或Java开发工具,是一个编写Java的Applet小程序和应用程序的程序开发环境。JDK是整个Java的核心,包括了Java运行环境,一些Java工具和Java的核心类库。2.2编程工具1.Ec......
  • L2-2 病毒溯源-Java
    题目L2-2病毒溯源病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变......
  • Google Earth Engine(GEE)——全球河流网络及相应的水资源区数据集
    全球河流网络及相应的水资源区河流网络和水资源区(WRZ)对于水资源的规划、利用、开发、保护和管理至关重要。目前,世界上的河网和水资源区大多是根据数字高程模型数据自动获得的,这些数据不够准确,尤其是在平原地区。此外,WRZ代码与河网不一致。作者提出了一系列方法,生成了分辨率较高、......
  • leetcode_打卡10
    leetcode_打卡10题目:283.移动零思路:双指针,数值互相交换,不是复制覆盖代码:classSolution{publicvoidmoveZeroes(int[]nums){intn=nums.length;intl=0,r=0;while(r<n){if(nums[r]!=0){swap(nums,l,r);......
  • leetcode_打卡09
    leetcode_打卡09题目:443.压缩字符串思路:双指针代码:classSolution{publicintcompress(char[]chars){intn=chars.length;intwrite=0,left=0;for(intread=0;read<n;read++){if(read==n-1||chars[r......
  • java 实现简单的http服务器
    1、废话不多说,代码如下packagecom.linhuaming.test;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.net.ServerSocket;importjava.net.Socket;/***http服务器测试*/publicclassHttpServerTest{publi......