引出
1.类什么时候被加载到JVM中,new,Class.forName: Class.forName(“包名.类名”);
2.创建对象的方式,反射,本质是获得类的类对象Class;
3.克隆clone,深拷贝,浅拷贝的对比;
4.序列化和反序列化的方式;
类什么时候被加载JVM中
Hello h; // 此时没有用Hello,jvm并没有进行类加载
- 看到new : new Book()
- Class.forName: Class.forName(“包名.类名”)
- 类加载器
package com.tianju.auth.reflect;
public class HelloTest1 {
public static void main(String[] args) throws ClassNotFoundException {
Hello h; // 此时没有用Hello,jvm并没有进行类加载
System.out.println("**********");
new Hello(); // new 的时候会加载到内存中
System.out.println("**********");
Class.forName("com.tianju.auth.reflect.Hello");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
package com.tianju.auth.reflect;
public class Hello {
static {
System.out.println("hello");
}
public Integer count(Integer a,Integer b){
return a+b;
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
int a = 3;
Class<?> aClass = Hello.class; // ?泛型的写法
Class<?> aClass1 = Class.forName("com.tianju.auth.reflect.Hello");
Class<? extends Hello> aClass2 = new Hello().getClass();
System.out.println(aClass);
System.out.println(aClass1);
System.out.println(aClass2);
Hello o = (Hello) aClass.newInstance();
int count = o.count(1, 2);
System.out.println(count);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
创建对象几种方式
1.new 看到new : new Book()
2.反射 Class.forName(“包名.类名”)
一个类会产生一个唯一的Class对象,JVM底层原理
Car.java 编译成 Car.clase 类加载到 JVM 中,加载时还没有创建对象;
进入JVM中给类Car创建单独的唯一的对象Class 类,该Class对象中存储了Car类的一些必要信息,没有记录相关的值;
以Class对象生产成多个Car对象,通过Class类映射出多个Car对象
如何获取Class对象【反射的基础】
- 对象.getClass()
- 类.class
- Class.forName(“包名.类名”)
案例:连接数据库方法
类加载采用了反射的方式
采用枚举方式封装JDBC单例
方法程序:
package com.tianju.util;
import java.sql.*;
import java.util.Objects;
/**
* 采用枚举单例封装数据库
*/
public enum DbUtilEnum {
INSTANCE;
private Connection conn;
private PreparedStatement pst;
private ResultSet rs;
private DbUtilEnum() {
// 注册驱动-类加载
register();
}
/**
* 第一步:注册驱动,类加载
*/
private void register(){
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
// 建立数据库连接
// 192.168.0.134:3306
// root,123
/**
* 第二步:建立数据库连接
* @param ipAdress ip地址+端口号
* @param user 用户名root
* @param password 密码123
*/
public void connect(String ipAdress,String user,String password){
String url = "jdbc:mysql://"+ipAdress+"/emp_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
try {
conn = DriverManager.getConnection(url,user,password);
System.out.println("成功连接数据库:"+ipAdress);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第三步:准备SQL语句,
* @param sql sql语句
*/
public void setPreparedStatement(String sql, Object...values){
try {
pst = conn.prepareStatement(sql);
// 逐个填充 ? 处的空缺
for (int i=0;i<values.length;i++){
pst.setObject(i+1, values[i]);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第四步:增加,删除,修改
*/
public void executeUpdate(){
try {
pst.executeUpdate();
System.out.println("执行增删改操作");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第四步:查询ResultSet,调用next()方法
* @return 返回查询的ResultSet
*/
public ResultSet executeQuery(){
try {
rs = pst.executeQuery();
System.out.println("执行查询操作,返回结果");
return rs;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 第五步:关闭连接
*/
public void close(){
try {
if (Objects.nonNull(rs)){
rs.close();
}
if (Objects.nonNull(pst)){
pst.close();
}
if (Objects.nonNull(conn)){
conn.close();
}
System.out.println("操作完成,关闭数据库连接");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
3.克隆(拷贝)clone
- 继承的时候,可以将子类的访问控制符扩大,但不能缩小;子类不得比父类抛出更多,更大的异常。
- 浅拷贝、深拷贝问题:
浅拷贝
// protected:代表本包或者继承
// 继承的时候,可以将子类的访问控制符扩大,但不能缩小;
// 子类不能比父类抛出更多的异常
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
深拷贝
public Book deepClone(){
Book book = new Book();
Author au = new Author();
au.setName(author.getName());
book.setAuthor(au);
book.setTitle(this.title);
book.setPrice(this.price);
return book;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
案例
Author.java实体类
package com.tianju.auth.reflect;
import lombok.Data;
@Data
public class Author {
private String name;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
Book.java实体类
implements Cloneable{ // 可以克隆的
package com.tianju.auth.reflect;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book implements Cloneable{ // 可以克隆的
private String title;
private Author author;
public double price;
static {
System.out.println("book的静态代码块");
}
// protected:代表本包或者继承
// 继承的时候,可以将子类的访问控制符扩大,但不能缩小;
// 子类不能比父类抛出更多的异常
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Book deepClone(){
Book book = new Book();
Author au = new Author();
au.setName(author.getName());
book.setAuthor(au);
book.setTitle(this.title);
book.setPrice(this.price);
return book;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
进行测试
package com.tianju.auth.reflect;
public class TestDemo{
public static void main(String[] args) throws CloneNotSupportedException {
Author author = new Author();
author.setName("吴承恩");
Book book = new Book("三国演义", author,12.56);
Book book1 = book;
System.out.println(book1==book);// == 两个引用是否指向同一个对象
// clone创建了一个新的对象,只是值一样
Book bookClone = (Book) book.clone();
// 深拷贝,创建了新的对象,上面的浅拷贝,只是拷贝了引用
Book deepClone = book.deepClone();
System.out.println(bookClone==book);
System.out.println("克隆前:"+book);
System.out.println("克隆后:"+bookClone);
author.setName("小柯基");
System.out.println("修改后的原对象:"+book);
System.out.println("修改后的clone对象:"+bookClone);
// 深拷贝
System.out.println("***********");
System.out.println("深拷贝的方法:"+deepClone);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
序列化和反序列化
对象流-把对象存储为dat文件
要点:
(1)实体类需要实现序列化接口 public class Car implements Serializable;【标记接口】
(2)序列化的版本号最好不要写,交给JVM实现,要保证版本号一致;
功能:
ObjectOutputStream—->对象写入文件
serialVersionUID :在序列化的时候指定的编号, 在反序列化时应该保证版本号一致。
案例:把car类存储到dat文件中
1)类需要实现序列化的接口
public class Car implements Serializable { // 需要实现序列化的接口
// 序列化的版本号,不要写,交给jvm实现;保证读的和写的对象实体类要一样
// private static final long serialVersionUID = 2L;
private Integer id;
private String name;
public Car() {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
2)从内存写入硬盘文件,为out,用write
ObjectOutputStream out =
new ObjectOutputStream(
new FileOutputStream("D:\\Myprogram\\idea-workspace\\IOStrem\\IOStrem\\src\\com\\woniuxy\\resources\\car.dat")
);
// 存多个的解决方法,存到List中
List<Car> list = new ArrayList<>();
list.add(new Car(1, "BMW"));
list.add(new Car(2, "BYD"));
list.add(new Car(3, "BMW"));
out.writeObject(list); // list也实现了Serializable
out.flush();
out.close();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
3)从硬盘读入内存,为in,用read
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream("D:\\Myprogram\\idea-workspace\\IOStrem\\IOStrem\\src\\com\\woniuxy\\resources\\car.dat")
);
// Car car = (Car) in.readObject(); // 读对象,向下转型
// System.out.println(car);
List<Car> list = (List<Car>) in.readObject();
System.out.println(list);
list.forEach(car -> System.out.println(car)); // list的lamda表达式
list.forEach(System.out::println); // 上面的简化写法
in.close(); // 记得关闭
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
总结
1.类什么时候被加载到JVM中,new,Class.forName: Class.forName(“包名.类名”);
2.创建对象的方式,反射,本质是获得类的类对象Class;
3.克隆clone,深拷贝,浅拷贝的对比;
4.序列化和反序列化的方式;
一、自我介绍
这个是我的 个人主页 : zxctscl
从2023年到现在一些小成就
我主要分享的文章是C语言和C++方面:
当然也有不少算法题:
二、年度回顾
在过去的一年里,也有不少收获:
在C++编程语言的学习方面取得了显著进展。掌握了编译时多态性的实现方法,同时深入理解了标准库迭代器的应用场景以及如何利用std::cout
输出容器中的元素。
对于动态规划类题目有了更深刻的认识,能够熟练运用状态转移方程解决复杂问题,如求解最长递增子序列长度。
而在C++编程语言的学习路径时,强调了实际操作的重要性1。理论知识固然重要,但通过编写代码来巩固所学概念同样不可或缺。对于希望深入理解这门强大而灵活的语言的人来说,在实践中不断尝试新功能和技术至关重要。
针对算法的学习,则建议利用高质量资源进行系统化训练。
三、技能提升方向
为了进一步提高技术水平并适应行业发展需求,计划在未来一年内重点加强以下几个方面的训练:
- 探索更多高级特性,比如协程(coroutine),模块化(modules)等新引入的功能;
- 加深对STL的理解程度,特别是各种容器内部机制及其性能特点;
- 继续钻研经典算法设计模式,尝试将其应用于实际项目开发过程中;
四、职业发展目标设定
短期目标是在现有基础上继续巩固基础理论知识体系的同时积极参与开源社区贡献代码;中期来看希望能够加入一家知名互联网企业担任核心研发岗位;长期愿景则是成长为一名技术专家或架构师级别的人物,在行业内具有一定影响力。
在研发小组中,希望加强对于现有业务逻辑的理解程度,争取成为团队内部的技术骨干成员之一。针对当前所负责的产品线开展专项研究工作,探索更多创新性的解决方案以满足日益增长的需求变化趋势。
对自己,就是做自己的领导,想从他人的总结出提炼出什么数据,无非就是我们完成了什么项目,在项目中做了什么事,有哪些价值高的事,有哪些问题做的不足(待改善),有哪些困难(寻求资源)以及下一年的工作目标(有规划)。才能更好更正,能有更好的发展。
五、 身体是革命的本钱
在2024年因为身体原因,住院接受了治疗。当生病之后才知道,健康是多么重要。希望大家在做一切任务之前,都得有一个健康的身体,爱护好自己身体,保持良好心情。
评论记录:
回复评论: