自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

qq_41934990的博客

我们各自努力,最高处见。

  • 博客(260)
  • 资源 (15)
  • 收藏
  • 关注

原创 什么是可重入锁?一文讲透多线程同步的核心机制

可重入锁(Reentrant Lock) 是指同一个线程可以多次获取同一把锁而不被阻塞的锁机制。它允许线程在持有锁的状态下,再次递归或嵌套地获取该锁,避免因自我阻塞导致的死锁。递归方法中,线程首次获取锁后,再次递归调用时无需等待自己释放锁。嵌套锁场景(如方法A调用方法B,两者使用同一把锁),线程无需重复竞争已持有的锁。典型实现:Java中的synchronized和ReentrantLock均为可重入锁。可重入锁通过线程标识+重入计数解决了自我阻塞、释放失控等问题,是支持递归和嵌套锁的关键机制。

2025-06-10 21:30:00 597

原创 深入解析 ReentrantLock:原理、公平锁与非公平锁的较量

ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。

2025-06-09 20:00:00 835

原创 Java 中 synchronized 和 ReentrantLock 的全面对比解析

synchronized:使用简单,适合对代码简洁性要求较高、并发程度不是特别高的场景,JVM 会自动处理锁的获取和释放。ReentrantLock:功能更强大,提供了更灵活的锁控制、公平锁、可中断锁获取和多个条件变量等特性,适合对锁的控制要求较高、并发场景复杂的情况,但需要手动管理锁的获取和释放。

2025-06-07 20:00:00 671

原创 微信小程序内容安全检测解决方案全流程详解(文本 + 图片/音频)

获取小程序全局唯一后台接口调用凭据,token有效期为7200s(2小时)

2025-06-06 17:06:55 707

原创 深入解析 Java 中的 synchronized:从使用到底层原理的全面详解

● 原理深度:结合对象头(Mark Word)、Monitor 机制、锁膨胀过程说明。● 优化意识:强调 JDK 版本优化(如偏向锁默认开启)和实际编码中的锁粒度控制。● 对比思维:与 ReentrantLock 的对比需结合场景(公平性、可中断性、性能)。● 陷阱规避:锁对象选择(避免 null、避免 String 常量等)、死锁场景分析。

2025-06-03 21:30:00 1033

原创 悲观锁与乐观锁:并发编程中的两种核心控制策略详解

悲观锁和乐观锁各有优缺点,在实际应用中,需要根据具体的业务场景来选择合适的锁策略。如果并发冲突较高,对数据一致性要求严格,建议使用悲观锁;如果并发冲突较少,追求高并发性能,可以考虑使用乐观锁。

2025-06-02 20:49:33 652

原创 Java 中 Lock 接口详解:灵活强大的线程同步机制

void lock():获取锁,如果锁不可用,则当前线程将被阻塞,直到锁被释放。void lockInterruptibly():可中断地获取锁,在获取锁的过程中,如果当前线程被中断,则会抛出 InterruptedException 异常。boolean tryLock():尝试非阻塞地获取锁,如果锁可用,则获取锁并返回 true;否则返回 false。

2025-05-31 21:44:03 973

原创 CAS会产生什么问题以及如何解决

例如,在某些情况下,可以设置一个最大重试次数,当超过这个次数时,放弃 CAS 操作,采用其他方式处理;● 问题描述:在 CAS 操作中,如果竞争非常激烈,CAS 操作可能会多次失败,从而导致线程不断地进行重试,这会消耗大量的 CPU 资源,使程序的性能下降。综上所述,CAS 是一种高效的并发操作机制,但在使用时需要注意其可能产生的问题,并根据具体场景选择合适的解决方案。在上述代码中,当 CAS 操作失败时,会进行重试,但最多重试 5 次,超过这个次数则放弃更新操作。2. 循环时间长开销大。

2025-05-29 17:36:40 654

原创 深入理解 Java 中的 volatile 关键字:多线程编程的得力助手

原子性是指一个操作是不可分割的,要么全部执行,要么全部不执行。简单来说,当一个变量被声明为 volatile 时,它会保证对该变量的写操作会立即刷新到主内存中,而读操作会从主内存中读取最新的值,从而确保不同线程之间对该变量的操作能够及时可见。在上述代码中,虽然 count 变量被声明为 volatile 变量,但最终输出的 count 值可能会小于 10000,这是因为 count++ 操作不是原子操作,多个线程可能会同时读取到相同的 count 值,然后进行加 1 操作,导致部分操作丢失。

2025-05-28 11:31:41 239

原创 SpringBoot+WebSocket双杀!三招搞定企业级聊天系统(附完整开源代码)

websocket官网介绍在线消息(双方都在线,正常发送消息)离线消息(一方不在线,发送消息储存起来,下次上线将存储的消息展示给对方看)群发消息(发送者将消息发送到所有在线的接收者)

2025-02-15 19:51:36 1162

原创 学会本篇文章,你也可以拥有自己的AI大模型

通过本文介绍的工具——OLLAMA和Chatbox AI,你已经掌握了从安装到运行的核心步骤。在 Chatbox AI的配置页面,输入你的AI访问令牌(API Key)。选择合适的系统版本:根据你的操作系统(Windows、MacOS或Linux)选择对应的版本进行下载。运行并配置:双击解压后的文件,等待安装完成。打开Chatbox AI界面,尝试发送一条简单的消息(例如“你好”),确保能够与AI模型成功通信。解压文件:将下载的exe文件解压到本地文件夹,例如 D:\IDE\Typora。

2025-02-05 19:59:25 863

原创 深入解析 HashMap 的 remove() 方法及其相关实现

HashMap 是 Java 中最常用的集合类之一,它提供了高效的键值对存储和检索功能。本文将详细解析 HashMap 的 remove() 方法及其相关的内部实现,包括 removeNode() 和 removeTreeNode() 方法。通过这些方法,我们可以了解 HashMap 如何高效地移除指定的键值对,并在必要时重新平衡红黑树结构。给出大致流程图,让我们来跟着流程图看源码。

2024-10-15 22:00:00 1338 1

原创 深入解析 HashMap 的 put() 方法及其相关实现

在 Java 编程中,HashMap 是一个非常常用且高效的集合类,用于存储键值对。它基于哈希表实现,提供了快速的插入、删除和查找操作。本文将深入探讨 HashMap 的 put() 方法及其相关的核心内部方法,包括如何处理哈希冲突、链表到红黑树的转换以及扩容机制。通过理解这些细节,你将能够更好地利用 HashMap 来优化你的应用程序,并解决可能出现的性能问题。先来看下hashMap插入数据的大致流程,以便我们接下来理解源码。

2024-10-12 08:30:00 1441

原创 深入理解 Java HashMap 的 get() 方法及其相关实现

在 Java 中,HashMap 是一个非常常用的数据结构,用于存储键值对。它提供了快速的查找、插入和删除操作。HashMap 的核心功能之一是根据键获取对应的值,这主要通过 get() 方法来实现。本文将详细介绍 HashMap 的 get() 方法及其相关的辅助方法,包括 getNode()、hash()、getTreeNode()、root()、find()、comparableClassFor() 和 compareComparables()。

2024-10-11 21:30:00 2007 6

原创 深入解析Java HashMap:从基础设置到内部结构

在Java集合框架中,HashMap 是一种非常高效且常用的数据结构,它基于哈希表实现,提供了快速的查找、插入和删除操作。理解 HashMap 的内部机制不仅对于日常开发至关重要,而且对于优化应用程序性能也有着重要作用。本文将详细探讨 HashMap 的基本属性、构造方法以及其内部节点 Node 的实现细节。通过这些内容,读者可以更深入地了解 HashMap 的工作原理,并能够更好地利用它来解决实际问题。下面我们来一步步掌握它。

2024-10-10 18:44:17 345

原创 PlantUML 时序图全面指南:从基础到高级

startumltitle 多行定义参与者=title----""参与者""A -> B@enduml。

2024-10-09 08:30:00 3615

原创 Java 8 Stream API:强大而灵活的数据处理流水线

Stream 中⽂称为 “流”,通过将集合转换为这么⼀种叫做 “流”的元素队列,通过声明性⽅式,能够对集合中的每个元素进⾏⼀系列并⾏或串⾏的流⽔线操作元素是特定类型的对象,所以元素集合看作⼀种流, 流在管道中传输, 且可以在管道的节点上进⾏处理, ⽐如 排序,聚合,过滤等操作操作详情数据元素便是原始集合,如list,set,map生成流,可以使串行流stream或者并行流parallelStream中间操作,可以使排序,聚合,过滤,转换等。

2024-09-09 09:00:00 873

原创 Java 8的关键新特性:Lambda表达式、Base64编码、日期时间API及Optional类

自从Java 8发布以来,它就标志着Java编程语言的一个重要转折点。这一版本不仅带来了诸多功能上的改进,还引入了一些革命性的特性,彻底改变了开发者编写代码的方式。Java 8的设计目标是让语言更加简洁、更具表现力,并且能够更好地适应多核处理器时代的需求。本文将探讨Java 8中最值得关注的新特性,包括Lambda表达式、Stream API、新的日期与时间API以及Optional类等。

2024-09-08 21:00:00 1111

原创 图形验证码从设计到实现

获取前端传过来的手机号以及图形验证码,根据ip以及网络地址相关西信息获取缓存key,根据key获取验证码,然后比较验证码是否一致,如果一致验证通过,删除缓存,执行发送短信相关业务。获取验证码的接口非常简单,调用验证码配置类获取验证码,将获取到的验证码缓存到redis中并设置过期时间,然后调用配置类传入验证码获取到图形验证码,通过IO流返回。上述我们主要讲述了用户登录获取验证码的逻辑,用户注册,找回密码逻辑都是差不多一样的,只是后续的处理不太一样,在这里就不再过多讲述了。再去看下校验验证码的这个接口,

2024-09-07 20:30:00 1488

原创 揭秘滑块图形验证码:从设计到实现的全过程

本文详细介绍了滑块图形验证码的生成逻辑及其后端实现细节。首先,根据项目需求选择合适的背景图片,并将其存储于项目的ClassPath或其他如云存储服务中。接着,服务器随机选取一张图片作为背景,并在其上随机裁剪出一个区域作为滑块,即所谓的“缺口”。此过程中的缺口参数(如位置、大小)是随机生成的,以此增加验证码的安全性。当用户请求需要验证的页面时,服务器将背景图与滑块图及验证所需的相关参数发送至前端。前端展示这些图像,并允许用户通过拖动滑块来填补缺口,以完成验证。

2024-08-26 08:54:28 1088

原创 Elasticsearch8.x聚合查询全面指南:从理论到实战

类似于SQL中的GROUP BY操作,根据指定的条件对数据进行分组统计。可以进行嵌套分桶,即在一个分桶的基础上再进行细分。示例:按照手机的品牌进行分桶统计数量,再在小米手机的分桶基础上按照档次进行二次分桶。语法格式指标聚合(Metrics Aggregations)主要用于计算数值字段的统计信息,如平均值、最大值、最小值、求和、去重计数等。示例:计算某个班级、某个学科的最高分、最低分等。语法格式聚合查询的特点嵌套性:聚合查询支持嵌套,即一个聚合内部可以包含别的子聚合,实现复杂的数据挖掘和统计

2024-06-27 20:30:00 2158

原创 ElasticSearch8.X查询DSL语法案例进阶实战

Query DSL主要由两部分组成:查询和过滤。查询部分:用于指定搜索条件和匹配规则。例如,可以使用match查询进行全文检索,term查询进行精确匹配,range查询进行范围匹配等。过滤部分:用于对查询结果进行进一步的筛选和过滤。与查询查询不同,过滤查询不会影响得分计算,只是对结果进行简单的筛选操作。fuzzy查询是Elasticsearch中提供的一种模糊匹配查询类型,用在搜索时容忍一些拼写错误或近似匹配使用fuzzy查询,可以根据指定的编辑距离(即词之间不同字符的数量)来模糊匹配查询词。

2024-06-26 22:15:00 1034

原创 深入解析Elasticsearch 8.4.1:Mapping与字段类型实战指南

在Elasticsearch中,Mapping定义了索引中每个字段的类型、属性以及设置。Mapping的作用是告诉Elasticsearch如何索引文档中的字段,包括如何分析字段值以及如何存储它们。分词即使将文本拆分成单独的单次或词项的过程分词是搜索引擎在建立索引和执行查询时的关键步骤,将文本拆分成单词,并构建倒排索引,可以实现更好的搜索和检索效果。分词规则是指如何将文本进行拆分的规则和算法。elasticsearch使用一些列的分词器(analyzer)和标记器(tokenizer)来处理文本内容。

2024-06-25 21:00:00 1885

原创 Elasticsearch 索引与文档操作实践指南

上节我们部署了elasticsearch8.4.1和kibana8.4.1以及ik分词器,本节我们来学习下elasticsearch的相关索引,文档操作。首先我们kinana的主界面找到开发者工具在里面我们来编写相关操作。

2024-06-24 22:18:59 836

原创 实战指南:部署Elasticsearch 8.4.1与Kibana 8.4.1并集成IK分词器

在本实战教程中,我们不仅解决了Docker镜像下载问题,通过配置镜像加速器顺利拉取了Elasticsearch与Kibana的最新镜像,还深入了解了如何自定义网络、优化容器启动参数,以及如何安全有效地启动这两个核心组件。这里有一个小错误,应该是-p 9200:9200 -p 9300:9300,分别将容器的9200端口(HTTP接口)和9300端口(TCP通信端口)映射到宿主机的相同端口,允许外部访问Elasticsearch服务。在Docker中,网络名称是唯一的,用于标识和引用特定的网络。

2024-06-23 20:52:51 1432

原创 XXL-Job实战(千万级短信推送实战)

经过细致的部署与实践,我们不仅成功搭建了基于XXL-Job的分布式短信发送系统雏形,还深入探索了其分片任务的强大功能,为应对双十一等大规模营销活动的短信推送挑战提供了强有力的技术支撑。可以看到,我们控制台也打印了相关日志,说明我们的demo执行成功了。名称就自己取一个就可以了,注册方式我们选择自动注册,也可以手动录入,看自己选择就可以了,选择保存,我们来到任务管理,选择添加任务。下面我们来开发我们的需求,在开发需求之前我们还需要了解下xxl-job中的分片任务,并以此来开发我们的需求。

2024-06-22 21:31:54 1540

原创 XXL-Job实战(一)

简单易用:Timer类提供了简单直观的API,使得开发者能够快速上手,实现基本的定时任务需求。创建一个定时任务只需几行代码即可完成。灵活性:Timer允许你安排任务在指定的延迟后执行一次,或者以固定的间隔重复执行。这对于很多简单的定时任务场景来说已经足够灵活。集成方便:作为Java标准库的一部分,Timer无需引入额外的依赖,可以直接在任何Java项目中使用,便于维护和移植单线程执行:Timer使用一个后台线程来执行所有安排的任务,这意味着所有任务都是串行执行的。

2024-06-20 21:31:39 1211

原创 SpringBoot运行流程源码分析------阶段三(Spring Boot外化配置源码解析)

首先看一下ApplicationArguments接口的具体方法定义及功能介绍。//返回原始未处理的参数(通过application传入的) String [ ] getSourceArgs();//返回所有参数的集合,如参数为:--foo=bar --debug,则返回【"foo","debug"】 Set < String > getOptionNames();//选项参数中是否包含指定名称的参数 boolean containsOption(String name);

2023-10-24 23:25:16 765

原创 SpringBoot运行流程源码分析------阶段二(run方法核心流程)

在上面的代码中,实例化监听器需要有一个默认的构造方法,且构造方法的参数为Class

2023-08-07 22:28:12 583 1

原创 算法------排序算法------插入排序法

插入排序法是将数组中的元素逐一已排好序的数据进行比较,先将前两个元素排好序,再将第三个插入适当的位置,以此类推,重复此步骤,知道排完序为止。

2023-06-26 21:48:47 230

原创 算法------排序算法------选择排序法

选择排序法也算是枚举法的应用,就是反复从未排序的数列中去除最小的元素加入到另一个数列中,最后的结果即为已排序的数列。选择排序法可以使用两种方式排序,即在所有的数据中,若从大到小排序,则将最大值放入第一个位置;若是从小到大排序,则将最小值放入到第一个位置。

2023-06-25 23:34:11 177

原创 算法------排序算法------冒泡排序法

冒泡排序法又称交换排序法,原理是从第一个元素开始,比较相邻元素的大小,如大小顺序有误,则对调后再进行下一个元素的比较,一次扫描之后可以确保最后一个元素位于正确的位置。接下来进行的第二次扫描,以此类推知道所有元素排序完成为止。例如下面的示例:由上图可知,5个元素的冒泡排序必须执行5-1次扫描,第一次扫描需要比较5-1次,第二次比较5-1-1次,以此类推,共比较4+3+2+1=10次。

2023-06-24 22:02:37 258

原创 SpringBoot构造流程源码分析------阶段一

在入口类主要通过SpringApplication的静态方法–run方法进行SpringApplication类的实例化操作,然后再针对实例化对象调用另一个run方法完成整个项目的初始化和启动。本章节重点围绕此过程的前半部分(即SpringApplication类的实例化)来讲解。//创建SpringApplication对象并执行某run方法 return(new SpringApplication(primarySources)) . run(args);

2023-06-20 22:39:25 830

原创 SpringBoot核心运行原理解析之------@Conditional条件注解

在SpringBoot核心运行原理解析之------@EnableAutoConfiguration文档中我们完成了自动配置类的读取和筛选,在这个过程中已经涉及了像@ConditionalOnClass这样的条件注解。打开每个自动配置类,都会看到@Conditional或其衍生的条件注解,本节我们来认识下@Conditional注解。

2023-05-17 21:11:52 880

原创 SpringBoot核心运行原理解析之-------@EnableAutoConfiguration

下面通过一张图来从整体了解AutoConfigurationImportSelector的核心功能及流程,然后再对照源码看具体的功能实现。当AutoConfigurationImportSelector被@Import注解引入之后,它的selectImports方法会被调用并执行其实现的自动装配逻辑。selectImports方法涵盖了组件自动装配的所有的处理逻辑。if(!if(!

2023-05-16 15:54:12 4695

原创 如何理解ThreadLocal

也就是说,调用ThreadLocal的set()方法存储的本地变量在具体线程的内存空间中,而ThreadLocal类支提供了set()和get()方法来存储和读取本地变量的值,当调用ThreadLocal类的set()方法时,把要存储的值存储在调用线程的threadLocals变量中,当调用ThreadLocal类的get()方法时,从当前线程的threadLocals变量中获取保存的值。保存数据时传递的key为当前ThreadLocal的this对象,而传递的value为调用set()方法传递的值。

2023-04-22 21:35:10 526

原创 如何理解线程池

当调用Executors.newSingleThreadExecutor方法创建线程池时,表示创建只有一个工作线程的线程池,即线程池中只有一个线程执行任务,能够保证提交到线程池中的所有任务按照先进先出的顺序,或者按照某个优先级的顺序来执行。如果在向线程池提交新任务时,线程池中无空闲线程,则新创建线程来执行任务。在调用shutdownNow()方法关闭线程时,线程池不能接受新提交的任务,也不能继续处理阻塞队列中的任务,同时,还会中断正在执行的线程,使得正在执行的任务被中断,线程池立即关闭并抛出异常。

2023-04-19 22:55:50 415

原创 如何理解CAS

ABA问题简单来说就是一个变量的初始值为A,被修改为B,然后再次被修改为A了。在使用CAS算法进行检测时,无法检测出A的值是否经历过被修改为B,又再次被修改为A的过程。

2023-04-08 15:09:53 904

原创 如何理解Lock

JDK层面提供了Lock锁都是通过Java提供的接口来手动解锁和释放锁的,所以在某种程度上,JDK中提供的Lock锁也叫显示锁、JDK提供的显示锁位于java.util.concurrent.locks包下,Lock接口的源码如下:lock()方法:阻塞模式抢占锁的方法。如果当前前程抢占锁成功,则继续向下执行程序的业务逻辑,否则,当前线程会阻塞。直到其他抢占到锁的线程释放锁后再继续抢占锁。lockInterruptibly()方法:可中断模式抢占锁的方法,当前线程在调用lockInterruptibl

2023-04-05 21:21:46 366

原创 如何理解AQS

这里需要结合acquireQueued()方法理解,当线程被唤醒后,会进入acquireQueued()方法中的if(p==head && tryAcquier(arg))逻辑判断,当条件成立是,被唤醒的线程会将自己所在的节点设置为head,表示已经获取到资源,此时,acquire()方法也执行完毕了。如果CAS操作设置成,则唤醒队列中的后继结点。在同步队列中,如果当前线程获取资源失败,就会通过addWaiter()方法将当前线程放入队列的尾部,并且保持自旋的状态,不判断自己所在的节点是否是队列的头结点。

2023-03-24 21:30:06 943

工行icbc对接demo

工行icbc对接demo,主要是对接工行的一些业务demo,工行微信支付,工行h5支付,支付回调,查询支付信息,查询订单信息,对账单下载,子商户注册,签名验签,工行支付相关jar包,相关api等

2023-05-17

工银聚富通支付异步通知报文参数

工银聚富通支付报文说明,具体参数介绍,异步回调请求报文说明,通知交易响应码,支付方式,订单状态,订单号等

2022-08-10

c++分数计算器课程大作业.rar

问题描述:定义一个整数类。定义一个分数类,有整数类派生。能对分数进行加减乘除运算和输入输出 功能需求:(1)定义整数类。包括构造函数,析构函数,显示函数 (2)输入输出:对流提取和流插入运算进行重载 (3)计算功能:可进行分数的加减乘除运算 (4)化简功能:将分数化简为最简分数 (5)菜单功能:每种功能的操作都在菜单中进行相应选择 ......... ..... ..

2019-12-19

诊所信息管理系统.cpp

本源代码使用Dev c++编写的诊所信息关系系统 ,使用的面向对象方法,切记不是面向过程,期末大作业大多使用的是面向对象,主要实现了增删改查等功能,使用Dev c++打开可以直接直接使用,无需修改代码

2020-04-19

hive(六)案例专用

hive六中案例所需要的资源,本案例是对sql语句的练习。

2018-08-21

sailing.rar

用于实现发送手机号获取验证码

2021-09-09

log4j.jar.rar

主要是log4j的jar包,里面包含了log4j的日志文件,希望对你有帮助

2021-04-22

jdkapi1.8.rar

该资源里内含java api 1.6中文版,java API 1.8中英文版,在学习java的过程中可以对比java API 1.6与1.8的差异,有利于我们更好地学习java

2021-03-29

6.数据库实战E_R图.docx

该文档是mysql专栏里的6数据库实战E_R图,由于文章中一直上传失败,就放在了我上传的资源里,有兴趣的可以看下。

2021-02-04

hive案例资源

本资源是hive四中的资源准备,希望对大家有用处,文件不大哦

2018-08-21

五子棋(菜鸟版).cpp

c++五子棋小项目,面向对象,适用于刚开始学习c++程序设计的入门学生,希望对那些入门学习c++的学生有点帮助

2020-06-02

比较实在的五子棋.cpp

该cpp是一个使用面向对象的编写的五子棋小项目,可以再vc6.0里直接打开运行,不会出现错误哦,也可以直接在Dev C++里直接打开使用,也是没问题的。希望该资源对那些需要写期末大作业的有帮助。

2020-06-03

网上书城jar包.rar

本jar包与分享的Javaweb网上书城项目搭配使用,如果想自己练习的话,可以下载导入自己的项目中,如果需要源码的可以给我留言,我可以无偿分享给你

2020-05-07

关于hibernate的查询,事务概念,复杂表的关系

如果你正在学hibernate框架,我认为这份文档对你会有很大的关系。 如果你真的需要可以下载啊,积分又不是很多是吧,关键能学到知识就行了

2018-06-22

通讯录管理系统.cpp

c++编写的通讯录管理系统,使用Dev c++可以直接运行使用。主要实现了添加,删除,修改,查询,显示等功能,一般人不容易操作哦

2020-04-19

java经典设计模式

java典型的设计模式,模式的创建,模型结构,该文件包括工厂模式,抽象模式等

2018-05-19

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除