码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • JAVA 泛型、序列化和复制


            泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。比如我们要写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,我们就可以使用 Java 泛型。

    1 泛型方法( ()

            你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

    1. // 泛型方法 printArray
    2. public static < E > void printArray( E[] inputArray )
    3. {
    4. for ( E element : inputArray ){
    5. System.out.printf( "%s ", element );
    6. }
    7. }

    1. 表示该通配符所代表的类型是 T 类型的子类。
    2. 表示该通配符所代表的类型是 T 类型的父类。

    2 泛型类

            泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。

    1. public class Box<T> {
    2. private T t;
    3. public void add(T t) {
    4. this.t = t;
    5. }
    6. public T get() {
    7. return t;
    8. }

    3 类型通配符?

            类 型 通 配 符 一 般 是 使 用 ? 代 替 具 体 的 类 型 参 数 。 例 如 List 在 逻 辑 上 是
    List,List 等所有 List<具体类型实参>的父类。

    4 类型擦除 

            Java 中的泛型基本上都是在编译器这个层次来实现的。在生成的 Java 字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个
    过程就称为类型擦除。如在代码中定义的 List和 List等类型,在编译之后
    都会变成 List。JVM 看到的只是 List,而由泛型附加的类型信息对 JVM 来说是不可见的。
    类型擦除的基本过程也比较简单,首先是找到用来替换类型参数的具体类。这个具体类一般
    是 Object。如果指定了类型参数的上界的话,则使用这个上界。把代码中的类型参数都替换
    成具体的类。

    5 JAVA 序列化( 创建可复用的 Java 对象)

    保存 ( 持久化 ) 对象 及其状态到内存或者磁盘
            Java 平台允许我们在内存中创建可复用的 Java 对象,但一般情况下,只有当 JVM 处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比 JVM 的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java 对象序列化就能够帮助我们实现该功能。
    序列化对象以字节数组保持 - 静态成员不保存
            使用 Java 对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的”状态”,即它的成员变量。由此可知,对
    象序列化不会关注类中的静态变量。
    序列化用户远程对象传输
            除了在持久化对象时会用到对象序列化之外,当使用 RMI(远程方法调用),或在网络中传递对象时,都会用到对象序列化。Java序列化API为处理对象序列化提供了一个标准机制,该API简单易用。
    Serializable 实现序列化
    在 Java 中,只要一个类实现了 java.io.Serializable 接口,那么它就可以被序列化。
    ObjectOutputStream 和 ObjectInputStream 对对象进行序列化及反序列化
    通过 ObjectOutputStream 和 ObjectInputStream 对对象进行序列化及反序列化。
    writeObject 和 readObject 自定义序列化策略
    在类中增加 writeObject 和 readObject 方法可以实现自定义序列化策略。
    序列化 ID
    虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个
    类的序列化 ID 是否一致(就是 private static final long serialVersionUID)

    序列化并不保存静态变量
    序列化子父类说明
    要想将父类对象也序列化,就需要让父类也实现 Serializable 接口。
    Transient 关键字 阻止该变量被序列化到文件中

    • 在变量声明前加上 Transient 关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
    • 服务器端给客户端发送序列化对象数据,对象中有一些数据是敏感的,比如密码字符串等,希望对该密码字段在序列化时,进行加密,而客户端如果拥有解密的密钥,只有在客户端进行反序列化时,才可以对密码进行读取,这样可以一定程度保证序列化对象的数据安全。

    6 JAVA 复制

             将一个对象的引用复制给另外一个对象,一共有三种方式。第一种方式是直接赋值,第二种方式是浅拷贝,第三种是深拷贝。所以大家知道了哈,这三种概念实际上都是为了拷贝对象。    

    6.1 直接赋值复制

            直接赋值。在 Java 中,A a1 = a2,我们需要理解的是这实际上复制的是引用,也就是
    说 a1 和 a2 指向的是同一个对象。因此,当 a1 变化的时候,a2 里面的成员变量也会跟
    着变化。

    6.2 浅复制(复制引用但不复制引用的对象)

            创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,
    那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。
    因此,原始对象及其副本引用同一个对象。

    class Resume implements Cloneable{
    public Object clone() {
    try {
    return (Resume)super.clone();
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    }
    }

        6.3 深复制(复制对象和其应用对象)

    深拷贝不仅复制对象本身,而且复制对象包含的引用指向的所有对象。

    1. class Student implements Cloneable {
    2. String name;
    3. int age;
    4. Professor p;
    5. Student(String name, int age, Professor p) {
    6. this.name = name;
    7. this.age = age;
    8. this.p = p;
    9. }
    10. public Object clone() {
    11. Student o = null;
    12. try {
    13. o = (Student) super.clone();
    14. } catch (CloneNotSupportedException e) {
    15. System.out.println(e.toString());
    16. }
    17. o.p = (Professor) p.clone();
    18. return o;
    19. }
    20. }

    6.4 序列化(深 clone 一中实现)

            在 Java 语言里深复制一个对象,常常可以先使对象实现 Serializable 接口,然后把对
    象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来,便可以重建对象。

  • 相关阅读:
    ES6--解构赋值-对象(object对象-{}展现 属性:值 )
    ctfshow文件包含
    【Unity3D赛车游戏优化篇】【十】汽车粒子特效和引擎咆哮打造极速漂移
    C#实现简单人机交互
    十年架构五年生活-09 五年之约如期而至
    数字孪生电力系统,可视化应用实现科学调度的电子设备
    Vue中的mixin(混入)
    Pandas to_sql 函数避坑指南「mssql字符乱码」
    Mybatis学习
    LVGL_基础控件timer
  • 原文地址:https://blog.csdn.net/Lj_chuxuezhe/article/details/133469762
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号