Java进阶(4)——结合类加载JVM的过程理解创建对象的几种方式:new,反射Class,克隆clone(拷贝),序列化反序列化

news2025/1/16 5:31:32

目录

  • 引出
  • 类什么时候被加载JVM中
  • 创建对象几种方式
  • 1.new 看到new : new Book()
  • 2.反射 Class.forName(“包名.类名”)
    • 如何获取Class对象【反射的基础】
    • 案例:连接数据库方法
  • 3.克隆(拷贝)clone
    • 浅拷贝
    • 深拷贝
      • 案例
  • 序列化和反序列化
    • 对象流-把对象存储为dat文件
  • 总结

引出


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");
    }
}
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.new 看到new : new Book()

2.反射 Class.forName(“包名.类名”)

一个类会产生一个唯一的Class对象,JVM底层原理

Car.java 编译成 Car.clase 类加载到 JVM 中,加载时还没有创建对象;

进入JVM中给类Car创建单独的唯一的对象Class 类,该Class对象中存储了Car类的一些必要信息,没有记录相关的值;

以Class对象生产成多个Car对象,通过Class类映射出多个Car对象

在这里插入图片描述
在这里插入图片描述

如何获取Class对象【反射的基础】

  1. 对象.getClass()
  2. 类.class
  3. Class.forName(“包名.类名”)

在这里插入图片描述

案例:连接数据库方法

在这里插入图片描述

类加载采用了反射的方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6IBnBmB-1683902514958)(D:\javalearn\思维导图笔记\mdPictures\image-20230512204643739.png)]

采用枚举方式封装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);
        }
    }
}

3.克隆(拷贝)clone

  • 继承的时候,可以将子类的访问控制符扩大,但不能缩小;子类不得比父类抛出更多,更大的异常。
  • 浅拷贝、深拷贝问题:

在这里插入图片描述

浅拷贝

在这里插入图片描述

    // 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;
    }

案例

Author.java实体类

package com.tianju.auth.reflect;

import lombok.Data;

@Data
public class Author {
    private String name;
}

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

进行测试

在这里插入图片描述

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

序列化和反序列化

对象流-把对象存储为dat文件

要点:

(1)实体类需要实现序列化接口 public class Car implements Serializable;【标记接口】

(2)序列化的版本号最好不要写,交给JVM实现,要保证版本号一致;

功能:

ObjectOutputStream—->对象写入文件

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

serialVersionUID :在序列化的时候指定的编号, 在反序列化时应该保证版本号一致。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ae2rqAoS-1683890070789)(D:\javalearn\思维导图笔记\mdPictures\image-20230508094242209.png)]

案例:把car类存储到dat文件中

1)类需要实现序列化的接口

public class Car implements Serializable { // 需要实现序列化的接口
    // 序列化的版本号,不要写,交给jvm实现;保证读的和写的对象实体类要一样
//    private static final long serialVersionUID = 2L;

    private Integer id;
    private String name;

    public Car() {
    }
}

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

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.类什么时候被加载到JVM中,new,Class.forName: Class.forName(“包名.类名”);
2.创建对象的方式,反射,本质是获得类的类对象Class;
3.克隆clone,深拷贝,浅拷贝的对比;
4.序列化和反序列化的方式;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/896789.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中大型无人机远程VHF语音电台系统方案

方案背景 中大型无人机在执行飞行任务时&#xff0c;特别是在管制空域飞行时地面航管人员需要通过语音与无人机通信。按《无人驾驶航空器飞行管理暂行条例》规定&#xff0c;中大型无人机应当进行适航管理。物流无人机和载人eVTOL都将进行适航管理&#xff0c;所以无人机也要有…

python ORM框架 sqlAlchemy

背景 最近在研究mysql的ORM框架&#xff0c;忽然看到了一个pip的包sqlalchemy&#xff0c;让我觉得很神奇&#xff0c;用下来的感觉和java的hibernate差不多&#xff0c;后边的链式查询又让我觉得和我很喜欢用的mybatis plus差不多&#xff0c;于是抱着好奇加上学习的态度&…

神经网络简单理解:机场登机

目录 神经网络简单理解&#xff1a;机场登机 ​编辑 激活函数&#xff1a;转为非线性问题 ​编辑 激活函数ReLU 通过神经元升维&#xff08;神经元数量&#xff09;&#xff1a;提升线性转化能力 通过增加隐藏层&#xff1a;增加非线性转化能力​编辑 模型越大&#xff0c;…

OpenCV 玩转图像和视频

为什么学OpenCV&#xff1f; • OpenCV ⽀持对图像缩放、旋转、绘制⽂字图形等基础操作 • OpenCV 库包含了很多计算机视觉领域常⻅算法&#xff1a;⽬标检测、⽬标跟踪等 OpenCV 简介 • OpenCV (Open Source Computer Vision) 是计算机视觉和机器学习软件库 • Intel 1999…

特殊数字专题

特殊数字 1.奇数2.偶数3.完数4.素数5.回文数6.水仙花数7.中位数9.随机数11.求年份&#xff1a;闰年12.求数字&#xff1a;两个整数的最大公约数及最小公倍数 1.奇数 代码案例&#xff1a; //输出所有1-1000之间的奇数 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h&…

Java虚拟机(JVM):虚拟机栈溢出

一、概念 Java虚拟机栈溢出&#xff08;Java Virtual Machine Stack Overflow&#xff09;是指在Java程序中&#xff0c;当线程调用的方法层级过深&#xff0c;导致栈空间溢出的情况。 Java虚拟机栈是每个线程私有的&#xff0c;用于存储方法的调用和局部变量的内存空间。每当…

Java二分法查找

二分法&#xff1a;首先需要一个由小到大排序好的数组&#xff0c;先找到其中间值&#xff0c;然后进行比较如果比较中间值大的话则向前找。如果比要找的小&#xff0c;则向后找。 代码实现&#xff1a; //定义查询方法 public static int searchTarget(int[] nums, int targ…

用户新增预测(Datawhale机器学习AI夏令营第三期)

文章目录 简介任务1&#xff1a;跑通Baseline实操并回答下面问题&#xff1a;如果将submit.csv提交到讯飞比赛页面&#xff0c;会有多少的分数&#xff1f;代码中如何对udmp进行了人工的onehot&#xff1f; 任务2.1&#xff1a;数据分析与可视化编写代码回答下面的问题&#xf…

【CSS动画02--卡片旋转3D】

CSS动画02--卡片旋转3D 介绍代码HTMLCSS css动画02--旋转卡片3D 介绍 当鼠标移动到中间的卡片上会有随着中间的Y轴进行360的旋转&#xff0c;以下是几张图片的介绍&#xff0c;上面是鄙人自己录得一个供大家参考的小视频&#x1f92d; 代码 HTML <!DOCTYPE html>…

上半年营收19亿,金融壹账通第二增长曲线“加速上坡”

8月16日&#xff0c;壹账通金融科技有限公司&#xff08;下称“金融壹账通”&#xff09;发布了截至2023年6月30日中期业绩报告。 根据财报&#xff0c;2023年上半年&#xff0c;金融壹账通实现营收18.99亿元&#xff0c;毛利润为6.96亿元&#xff1b;归母净利润率从-26.1%提升…

(ElementPlus)操作(不使用 ts): Form表单检验、规则及案例分析(这一篇就够了)

Ⅰ、Form 表单检验简介&#xff1a; 1、什么是 Form 表单检验&#xff1f; 其一、属性&#xff1a; 表单验证是 javascript 中的高级选项之一&#xff1b; 其二、定义&#xff1a; JavaScript 在数据被送往服务器前对 HTML 中的 Form 表单中的这些输入数据进行验证的行为就…

MySQL索引介绍 为什么mysql使用B+树

什么是索引&#xff1f; 索引是一种用于快速查询和检索数据的数据结构&#xff0c;常见的索引结构有&#xff1a;B树&#xff0c;B树和Hash。 索引的作用就相当于目录。打个比方&#xff0c;我们在查字典的时候&#xff0c;如果没有目录&#xff0c;那我们就只能一页一页的去…

文本三剑客之sed编辑器

sed 一、sed简介1.1 什么是sed&#xff1f;1.2 sed原理1.3 sed核心功能 二、sed命令格式详解2.1 命令格式2.2 常用选项2.3 sed脚本语法2.3.1 基本语法结构2.3.2 地址部分-----指定匹配范围2.3.3 命令部分-----要执行的命令 三、sed查找替换3.1 基本语法3.2 分组后向引用3.3 变量…

.NET应用UI组件DevExpress XAF v23.1 - 全新的日程模块

DevExpress XAF是一款强大的现代应用程序框架&#xff0c;允许同时开发ASP.NET和WinForms。DevExpress XAF采用模块化设计&#xff0c;开发人员可以选择内建模块&#xff0c;也可以自行创建&#xff0c;从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。 在新版中…

【爬虫练习之glidedsky】爬虫-基础2

题目 链接 爬虫往往不能在一个页面里面获取全部想要的数据&#xff0c;需要访问大量的网页才能够完成任务。 这里有一个网站&#xff0c;还是求所有数字的和&#xff0c;只是这次分了1000页。 思路 找到调用接口 可以看到后面有个参数page来控制页码 代码实现 import reques…

Python功能制作之简单的3D特效

需要导入的库&#xff1a; pygame: 这是一个游戏开发库&#xff0c;用于创建多媒体应用程序&#xff0c;提供了处理图形、声音和输入的功能。 from pygame.locals import *: 导入pygame库中的常量和函数&#xff0c;用于处理事件和输入。 OpenGL.GL: 这是OpenGL的Python绑定…

win10下IDEA搭建web项目脚手架

参考 IDEA运行Maven项目配置全过程(菜鸟专属)_idea配置maven_Hi梅的博客-CSDN博客 下载 IDEA 下载JDK 1.8 https://pan.baidu.com/s/1lj2na9omGwhPrCKYNz1qSQ 提取码:izkj 点击exe一步步next 添加环境变量: JAVA_HOME 对于自己jdk的路径 添加系统变量PATH:%JAVA_H…

混杂接口模式---vlan

策略在两个地方可以用--1、重发布 2、bgp邻居 2、二层可以干的&#xff0c;三层也可以干 3、未知单播&#xff1a;交换机的MAC地址表的记录保留时间是5分钟&#xff0c;电脑的ARP表的记录保留时间是2小时 4、route recursive-lookup tunnel 华为默认对于bgp学习来的路由不开启标…

在Hive/Spark上执行TPC-DS基准测试 (PARQUET格式)

在上一篇文章:《在Hive/Spark上运行执行TPC-DS基准测试 (ORC和TEXT格式)》中,我们介绍了如何使用 hive-testbench 在Hive/Spark上执行TPC-DS基准测试,同时也指出了该项目不支持parquet格式。 如果我们想要生成parquet格式的测试数据,就需要使用其他工具了。本文选择使用另…

深入了解Maven(一)

目录 一.Maven介绍与功能 二.依赖管理 1.依赖的配置 2.依赖的传递性 3.排除依赖 4.依赖的作用范围 5.依赖的生命周期 一.Maven介绍与功能 maven是一个项目管理和构建工具&#xff0c;是基于对象模型POM实现。 Maven的作用&#xff1a; 便捷的依赖管理&#xff1a;使用…