【设计模式——学习笔记】23种设计模式——原型模式Prototype(原理讲解+应用场景介绍+案例介绍+Java代码实现)

本文涉及的产品
系统运维管理,不限时长
简介: 【设计模式——学习笔记】23种设计模式——原型模式Prototype(原理讲解+应用场景介绍+案例介绍+Java代码实现)

原型模式

介绍

  • 原型模式指用通过拷贝原型实例创建新的实例,新实例和原型实例的属性完全一致
  • 原型模式是一种创建型设计模式
  • 工作原理是通过调用原型实例的 clone()方法来完成克隆,原型实例需要实现Cloneable接口,并重写clone()方法
  • 需要为每个类开发一个克隆方法,这对全新的类来说不难,但对已有类进行改造时,需要修改其源代码,违背了ocp原则
  • 实现深拷贝的时候可能需要比较复杂的代码

应用场景

在以下情况下,我们就不能根据new 类名()来生成实例,而是克隆现有实例来生成新实例

  • 对象种类繁多,无法将它们整合到一个类中(在软件设计中,有时候我们需要创建一种类型的对象,但是该类型下有多个具体的变体,这些变体之间可能存在大量差异,无法将这些变体都封装到一个类中。这时候可以使用原型模式,将这些变体作为原型,通过对原型进行克隆来得到新的对象。这样既避免了创建过多的分类,又能够保持对象的个性化)
  • 难以通过new来创建实例(有的实例非常复杂,想要创建一个一模一样的示例非常困难)
  • 想解耦框架与生成的实例时(想要让生成实例的框架不依赖于具体的类。这时,不能指定类名来生成实例,而要事先“注册”一个“原型”实例,然后通过复制该实例来生成新的实例)

类图

  • Prototype : 原型类,声明一个克隆自身的接口
  • ConcretePrototype: 具体的原型类,实现克隆方法
  • Client:调用原型对象的克隆方法,让一个原型对象克隆自身来创建一个属性一样的新对象

案例分析

克隆羊问题

现在有一只羊叫做tom,其属性为姓名: tom,年龄: 1,颜色:白色,请编写程序创建和 tom 属性完全相同的10只羊。

传统实现

package com.atguigu.prototype;
public class Sheep {
    private String name;
    private int age;
    private String color;
    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
    }
}
package com.atguigu.prototype;
public class Client {
   public static void main(String[] args) {
      // TODO Auto-generated method stub
      //传统的方法
      Sheep sheep = new Sheep("tom", 1, "白色");
      Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
      //....
      System.out.println(sheep);
      System.out.println(sheep2);
      System.out.println(sheep3);
      System.out.println(sheep4);
      System.out.println(sheep5);
      //...
   }
}
分析

【优点】

  • 比较好理解,简单易操作

【缺点】

  • 在创建新的对象时,需要获取原始对象的属性,如果创建的对象比较复杂时,效率较低,不够灵活(原型对象的属性修改之后,如添加一个属性,需要往构造方法中添加参数)
  • 总是需要重新初始化对象,而不能动态地获得对象运行时的状态

【改进】

  • 使用原型模式:在Java中,Obiect类是所有类的根类,Object类提供了一个clone()方法,该方法可以将一个Java对象复制一份,但是需要实现clone的Java类必须要实现一个接口Cloneable,该接口表示该类能够复制且具有复制的能力

原型模式(浅拷贝)

package com.atguigu.prototype.improve;
/**
 * 继承Cloneable
 */
public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;
    private String address = "蒙古羊";
    /**
     * 是对象, 克隆是会如何处理
     */
    public Sheep friend;
    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";
    }
    /**
     * 克隆该实例,使用默认的clone方法来完成
     *
     * @return
     */
    @Override
    protected Object clone() {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }
}
package com.atguigu.prototype.improve;
public class Client {
   public static void main(String[] args) {
      System.out.println("原型模式完成对象的创建");
      Sheep sheep = new Sheep("tom", 1, "白色");
      sheep.friend = new Sheep("jack", 2, "黑色");
      Sheep sheep2 = (Sheep)sheep.clone();
      Sheep sheep3 = (Sheep)sheep.clone();
      Sheep sheep4 = (Sheep)sheep.clone();
      Sheep sheep5 = (Sheep)sheep.clone();
      System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());
      System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode());
      System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode());
      System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode());
   }
}
原型模式完成对象的创建
sheep2 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep2.friend=1554874502
sheep3 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep3.friend=1554874502
sheep4 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep4.friend=1554874502
sheep5 =Sheep [name=tom, age=1, color=白色, address=蒙古羊]sheep5.friend=1554874502
Process finished with exit code 0

【分析】

  • 根据输出,可以看到其他sheep的friend原型对象的friend是同一个对象(因为hashcode一样),原因:上面的代码是浅拷贝,浅拷贝并不会重新复制一个引用类型的对象出来,只是单纯将克隆对象的friend指向原型对象的friend对象,这样的坏处是,如果原型对象的friend发生了改变,克隆对象的friend也会改变,这样不能算是真正的克隆

原型模式(深拷贝)

package com.atguigu.prototype.deepclone;
import java.io.Serializable;
public class DeepCloneableTarget implements Serializable, Cloneable {
   private static final long serialVersionUID = 1L;
   private String cloneName;
   private String cloneClass;
   /**
    * 构造器
    * @param cloneName
    * @param cloneClass
    */
   public DeepCloneableTarget(String cloneName, String cloneClass) {
      this.cloneName = cloneName;
      this.cloneClass = cloneClass;
   }
   /**
    * 因为该类的属性,都是String , 因此我们这里使用默认的clone完成即可
    * @return
    * @throws CloneNotSupportedException
    */
   @Override
   protected Object clone() throws CloneNotSupportedException {
      return super.clone();
   }
}
package com.atguigu.prototype.deepclone;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class DeepProtoType implements Serializable, Cloneable {
    /**
     * 基本数据类型
     */
    public String name;
    /**
     * 引用类型
     */
    public DeepCloneableTarget deepCloneableTarget;
    public DeepProtoType() {
        super();
    }
    /**
     * 深拷贝 - 方式 1 使用clone 方法
     *
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //这里完成对基本数据类型(属性)和String的克隆
        Object deep = super.clone();
        //对引用类型的属性,进行单独处理
        DeepProtoType deepProtoType = (DeepProtoType) deep;
        deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
        return deepProtoType;
    }
    /**
     * 深拷贝 - 方式2 通过对象的序列化实现 (推荐)
     * @return
     */
    public Object deepClone() {
        /// 创建流对象
        // 字节输出流
        ByteArrayOutputStream bos = null;
        // 对象输出流
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            //当前这个对象以对象流的方式输出
            oos.writeObject(this);
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepProtoType copyObj = (DeepProtoType) ois.readObject();
            return copyObj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }
        }
    }
}

客户端调用】

package com.atguigu.prototype.deepclone;
public class Client {
   public static void main(String[] args) throws Exception {
      // TODO Auto-generated method stub
      DeepProtoType p = new DeepProtoType();
      p.name = "宋江";
      p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");
      //方式1 完成深拷贝
      DeepProtoType p2 = (DeepProtoType) p.clone();
      System.out.println("p.name=" + p.name + "; p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
      System.out.println("p2.name=" + p.name + "; p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
      //方式2 完成深拷贝
      DeepProtoType p3 = (DeepProtoType) p.deepClone();
      System.out.println("p3.name=" + p.name + "; p3.deepCloneableTarget=" + p3.deepCloneableTarget.hashCode());
   }
}

【运行】

p.name=宋江; p.deepCloneableTarget=1554874502
p2.name=宋江; p2.deepCloneableTarget=1846274136
p3.name=宋江; p3.deepCloneableTarget=932172204
Process finished with exit code 0

【分析】

可以看到三个对象的deepCloneableTarget的hashCode不同,因此克隆成功

字符串修饰问题

【框架】

package framework;
import java.lang.Cloneable;
public interface Product extends Cloneable {
    /**
     * 实例使用
     * @param s
     */
    public abstract void use(String s);
    /**
     * 实例复制
     * @return
     */
    public abstract Product createClone();
}
package framework;
import java.util.*;
public class Manager {
    /**
     * 存储实例名及实例
     */
    private HashMap showcase = new HashMap();
    /**
     * 注册示例
     * @param name
     * @param proto
     */
    public void register(String name, Product proto) {
        showcase.put(name, proto);
    }
    /**
     * 根据实例名称使用实例
     * @param protoname
     * @return
     */
    public Product create(String protoname) {
        Product p = (Product) showcase.get(protoname);
        return p.createClone();
    }
}

【实现类】

import framework.*;
/**
 * use 方法的作用是将字符串用双引号括起来显示,并在字符串下面加上下划线。例如,当 ulchar 保存的字符为'~' 方法接收到的字符串为Hello时,显示结果如下
 *
 * "Hellor"
 *  ~~~~~~
 */
public class UnderlinePen implements Product {
    private char ulchar;
    public UnderlinePen(char ulchar) {
        this.ulchar = ulchar;
    }
    public void use(String s) {
        int length = s.getBytes().length;
        System.out.println("\"" + s + "\"");
        System.out.print(" ");
        for (int i = 0; i < length; i++) {
            System.out.print(ulchar);
        }
        System.out.println("");
    }
    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}
import framework.*;
/**
 * decochar字段中保存的是像装饰方框那样的环绕着字符串的字符。use方法会使用decochar字段中保存的字符把要显示的字符串框起来。
 * 例如,当decochar 中保存的字符为'*',use方法接收到的字符串为 Hello 的时候,显示结果如下
 * <p>
 * *******
 * *Hello*
 * *******
 */
public class MessageBox implements Product {
    private char decochar;
    public MessageBox(char decochar) {
        this.decochar = decochar;
    }
    public void use(String s) {
        int length = s.getBytes().length;
        for (int i = 0; i < length + 4; i++) {
            System.out.print(decochar);
        }
        System.out.println("");
        System.out.println(decochar + " " + s + " " + decochar);
        for (int i = 0; i < length + 4; i++) {
            System.out.print(decochar);
        }
        System.out.println("");
    }
    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

【主类】

import framework.*;
public class Main {
    public static void main(String[] args) {
        // 准备
        Manager manager = new Manager();
        UnderlinePen upen = new UnderlinePen('~');
        MessageBox mbox = new MessageBox('*');
        MessageBox sbox = new MessageBox('/');
        manager.register("strong message", upen);
        manager.register("warning box", mbox);
        manager.register("slash box", sbox);
        // 生成
        Product p1 = manager.create("strong message");
        p1.use("Hello, world.");
        System.out.println();
        Product p2 = manager.create("warning box");
        p2.use("Hello, world.");
        System.out.println();
        Product p3 = manager.create("slash box");
        p3.use("Hello, world.");
    }
}
"Hello, world."
 ~~~~~~~~~~~~~
*****************
* Hello, world. *
*****************
/
/ Hello, world. /
/
Process finished with exit code 0

分析

对象种类繁多,无法将它们整合到一个类中时

示例程序中,一共出现了如下3种样式。

  • 使用’~'为字符串添加下划线
  • 使用’*'为字符串添加边框
  • 使用’/'为字符串添加边框

本例比较简单,只生成了3种样式,不过无论多少种样式都可以生成。但是如果将每种样式都编写为一个类,类的数量将会非常庞大,源代码的管理也会变得非常困难。

想解耦框架与生成的实例时

在示例程序中,我们将复制(clone)实例的部分封装在framework包中了

在Manager类的create方法中,我们并没有使用类名,而是根据"strong message"和"slash box"等字符串(即实例名称)来生成相应的实例。与Java语言自带的生成实例的newSomething()方式相比,这种方式具有更好的通用性,且将框架从类名的束缚中解脱出来了

登场角色

  • Prototype(原型):定义用于复制现有实例来生成新实例的方法,如上面的Product
  • ConcretePrototype(具体的原型):负责实现复制现有实例并生成新实例的方法,如上面的MessageBox和UnderlinePen
  • Client(使用者):负责使用复制实例的方法生成新的实例,如上面的Manager

Spring源码分析

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 <!-- 这里我们的 scope="prototype" 即 原型模式来创建 -->
 <bean id="id01" class="com.atguigu.spring.bean.Monster" 
   scope="prototype"/>
</beans>

scope=“prototype”:使用原型模式

package com.atguigu.spring.bean;
/**
 * 注释
 * @author Administrator
 *
 */
public class Monster {
   private Integer id = 10 ;
   private String nickname = "牛魔王";
   private String skill = "芭蕉扇";
   public Monster() {
      System.out.println("monster 创建..");
   }
   public Monster(Integer id, String nickname, String skill) {
      //System.out.println("Integer id, String nickname, String skill被调用");
      this.id = id;
      this.nickname = nickname;
      this.skill = skill;
   }
   public Monster( String nickname, String skill,Integer id) {
      this.id = id;
      this.nickname = nickname;
      this.skill = skill;
   }
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   public String getNickname() {
      return nickname;
   }
   public void setNickname(String nickname) {
      this.nickname = nickname;
   }
   public String getSkill() {
      return skill;
   }
   public void setSkill(String skill) {
      this.skill = skill;
   }
   @Override
   public String toString() {
      return "Monster [id=" + id + ", nickname=" + nickname + ", skill="
            + skill + "]";
   }
}
package com.atguigu.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ProtoType {
   public static void main(String[] args) {
      // TODO Auto-generated method stub
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
      // 获取monster[通过id获取monster]
      Object bean = applicationContext.getBean("id01");
      System.out.println("bean" + bean); // 输出 "牛魔王" .....
      Object bean2 = applicationContext.getBean("id01");
      System.out.println("bean2" + bean2); //输出 "牛魔王" .....
      System.out.println(bean == bean2); // false,并不是同一个对象,只是属性相同
   }
}

【运行】

monster 创建..
beanMonster [id=10, nickname=牛魔王, skill=芭蕉扇]
monster 创建..
bean2Monster [id=10, nickname=牛魔王, skill=芭蕉扇]
false
Process finished with exit code 0

浅拷贝和深拷贝

浅拷贝

  • 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象
  • 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值 (内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值
  • sheep = (Sheep) super.clone()这种方式就是浅拷贝

深拷贝

  • 复制对象的所有基本数据类型的成员变量值
  • 为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象

【实现方式】

  • 重写clone方法来实现深拷贝(缺点:麻烦,每个子对象都需要调用克隆方法重新赋值)
  • 通过对象序列化实现深拷贝(缺点:速度慢,如果调用拷贝的次数多,不要使用这种方式)

深拷贝工具类

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class DeepCloneUtil {
   public static Object deepClone(Object srcObject){
      ByteArrayOutputStream bos = null;
      ObjectOutputStream oos = null;
      ByteArrayInputStream bis = null;
      ObjectInputStream ois = null;
      Object result = null;
      try {
         bos = new ByteArrayOutputStream();
         oos = new ObjectOutputStream(bos);
         oos.writeObject(srcObject);
         bis = new ByteArrayInputStream(bos.toByteArray());
         ois = new ObjectInputStream(bis);
         result = ois.readObject();
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         try {
            bos.close();
            oos.close();
            bis.close();
            ois.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      return result;
   }
}

使用方式

A a = new A();
A a1 = (A)DeepCloneUtil.deepClone(a);

clone方法与Clonable接口

  • Object中定义了clone()方法,如果类实现了Cloneable接口,就可以调用clone()来进行实例复制;否则调用就会报CloneNotSupportedException异常
  • Cloneable接口中并没有声明任何方法。它只是被用来标记“可以使用clone方法进行复制”的,称为标记接口(marker interface)
  • clone 方法只会进行复制,并不会调用被复制实例的构造函数。此外,对于在生成实例时需要进行特殊的初始化处理的类,需要自已去实现 clone 方法,在其内部进行这些初始化处理

文章说明

  • 本文章为本人学习尚硅谷的学习笔记,文章中大部分内容来源于尚硅谷视频(点击学习尚硅谷相关课程),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对尚硅谷的优质课程表示感谢。
  • 本人还同步阅读《图解设计模式》书籍(图解设计模式/(日)结城浩著;杨文轩译–北京:人民邮电出版社,2017.1),进而综合两者的内容,让知识点更加全面
目录
相关文章
|
23天前
|
存储 Java 关系型数据库
高效连接之道:Java连接池原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。频繁创建和关闭连接会消耗大量资源,导致性能瓶颈。为此,Java连接池技术通过复用连接,实现高效、稳定的数据库连接管理。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接池的基本操作、配置和使用方法,以及在电商应用中的具体应用示例。
41 5
|
1月前
|
存储 算法 Java
Java HashSet:底层工作原理与实现机制
本文介绍了Java中HashSet的工作原理,包括其基于HashMap实现的底层机制。通过示例代码展示了HashSet如何添加元素,并解析了add方法的具体过程,包括计算hash值、处理碰撞及扩容机制。
|
12天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
12天前
|
Java
Java之CountDownLatch原理浅析
本文介绍了Java并发工具类`CountDownLatch`的使用方法、原理及其与`Thread.join()`的区别。`CountDownLatch`通过构造函数接收一个整数参数作为计数器,调用`countDown`方法减少计数,`await`方法会阻塞当前线程,直到计数为零。文章还详细解析了其内部机制,包括初始化、`countDown`和`await`方法的工作原理,并给出了一个游戏加载场景的示例代码。
Java之CountDownLatch原理浅析
|
14天前
|
Java 索引 容器
Java ArrayList扩容的原理
Java 的 `ArrayList` 是基于数组实现的动态集合。初始时,`ArrayList` 底层创建一个空数组 `elementData`,并设置 `size` 为 0。当首次添加元素时,会调用 `grow` 方法将数组扩容至默认容量 10。之后每次添加元素时,如果当前数组已满,则会再次调用 `grow` 方法进行扩容。扩容规则为:首次扩容至 10,后续扩容至原数组长度的 1.5 倍或根据实际需求扩容。例如,当需要一次性添加 100 个元素时,会直接扩容至 110 而不是 15。
Java ArrayList扩容的原理
|
21天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
39 2
|
24天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
21天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
32 1
|
27天前
|
存储 安全 Java
深入理解Java中的FutureTask:用法和原理
【10月更文挑战第28天】`FutureTask` 是 Java 中 `java.util.concurrent` 包下的一个类,实现了 `RunnableFuture` 接口,支持异步计算和结果获取。它可以作为 `Runnable` 被线程执行,同时通过 `Future` 接口获取计算结果。`FutureTask` 可以基于 `Callable` 或 `Runnable` 创建,常用于多线程环境中执行耗时任务,避免阻塞主线程。任务结果可通过 `get` 方法获取,支持阻塞和非阻塞方式。内部使用 AQS 实现同步机制,确保线程安全。
|
1月前
|
开发框架 Java 程序员
揭开Java反射的神秘面纱:从原理到实战应用!
本文介绍了Java反射的基本概念、原理及应用场景。反射允许程序在运行时动态获取类的信息并操作其属性和方法,广泛应用于开发框架、动态代理和自定义注解等领域。通过反射,可以实现更灵活的代码设计,但也需注意其性能开销。
47 1
下一篇
无影云桌面