![](https://img-blog.csdnimg.cn/direct/08ea747a24374470ad3bce8c58a0e046.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
Java
文章平均质量分 85
博主自己学习过程中总结概括的Java知识点
程序猿ZhangSir
这个作者很懒,什么都没留下…
展开
-
Java泛型详解(史上最全泛型知识详解)
泛型是在JDK5之后引入的一个新特性,可以在编译阶段约束操作的数据类型,并进行检查。泛型的格式为用大白话来说,泛型就好比是给一个标签,通常情况下我们会在开发过程中或者个人学习或练习的过程中使用到泛型;就拿数组的泛型举例来说,我们把数组比作一个药瓶子,我们药瓶子贴上了什么标签,就只能放什么药,如果不管什么药都放在一个药瓶子里,那不得出大事吗?同样容器(数组)写上什么泛型,就只能存放什么数据;这样就不会导致我们存取数据的混乱。这样就解决了我们引言中提到的问题,也就解释了什么是泛型。原创 2023-07-25 14:00:00 · 7015 阅读 · 5 评论 -
Java反射全面详解
首先听这个名字就有些疑惑,什么是反射,它能用来干什么呢?Java官方对反射的解释是 "反射允许对封装类的字段,方法和构造函数进行编程式访问"。这里的字段指的就是成员变量,方法指的就是成员方法,构造函数就是构造方法。原创 2023-08-02 13:01:58 · 214 阅读 · 0 评论 -
线程池工作原理深入解析
线程池的好处就是,我们可以在线程池中创建多个线程,当我们有业务需要用到线程时,它会自动到线程池中拿取已经存在线程而不会再去创建新的线程,当线程完成了业务需求后,它会把使用过的线程再还到线程池中而不会销毁它,等待下一次任务的执行,如此一来,就节省了线程的创建与销毁这一动作,提高了程序的运行效率。(2)当我们需要用到线程时,线程池会去创建新的线程对象,当任务执行完毕之后,它会把线程归还给线程池,下次再有业务需要用到线程时,不会去创建新的线程,直接复用线程池中已经存在的线程。这里我就随便拿两个当例子说一下。原创 2023-08-10 13:30:00 · 2192 阅读 · 0 评论 -
深入理解集合的迭代器 Iterator,为什么遍历数组时删除元素不能直接使用remove()方法而需要使用迭代器?你有了解过原因吗?
如下所示,Itr 是 ArrayList 的一个内部类,它实现了 Iterator 迭代器接口,我画线的 expectedModCount 翻译过来意为期望修改次数,modCount 赋值给了 expectedModCount,也就是说,当我们创建了 iterator 对象之后,当前数组的修改次数 modCount 的值就会赋值给 excepectedModCount。在 Iterator 接口中,有两个非常重要的方法,hasNext()和next(),它是迭代器的核心方法。" 后面已经没有元素了,所以。原创 2023-09-23 12:00:00 · 1568 阅读 · 0 评论 -
开发常用的实体属性转化API,copyProperties方法的用途,需要注意的点。
在开发过程中,我们通常会在 Entity,model,DTO,VO,POJO,Param 等众多实体类之间进行互相转换,传统的做法就是 new 一个新的要转化的对象然后一个属性一个属性的 set 进去,如果是集合,外边再加一层循环嵌套即可,但尽管如此,步骤还是较为繁琐,而且当实体类中的属性较多时,代码还会显得特别臃肿,不美观。原创 2024-05-15 13:42:30 · 674 阅读 · 0 评论 -
null和空集合有什么区别?集合List的判断 list == null,list.size() == 0,isEmpty() == true有什么区别和联系?
集合 List 是我们在开发过程中非常常用的,这两天我在做一个功能的时候,用 PostMan 测试接口总是报空指针异常,后来经过调试发现了问题所在,原因就是对于数组的判断方式有误;所以写这篇文章记录下来,防止以后再犯类似的错误,也为了给小伙伴分享让小伙伴们在日后开发过程中也可以避。原创 2024-05-08 20:12:39 · 860 阅读 · 0 评论 -
final 关键字的用法?
final关键字的用法非常多,它可以修饰类,可以修饰方法,可以修饰变量,可以修饰基本数据类型,也可以修饰引用数据类型,接下来我们就自己分析它的用法。原创 2023-07-12 11:30:00 · 105 阅读 · 0 评论 -
Java中重写和重载的区别?
重写:发生在父子类中,方法名,参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类就不能重写该方法。重载:发生在同一个类中,方法名必须相同,参数类型不同,个数不同,顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。原创 2023-07-13 12:30:00 · 23 阅读 · 0 评论 -
一篇文章带你学会匿名内部类,由浅入深,一定手把手教会你
听名字就能看得出来,内部类,就是定义类中的一个类。在A类中定义一个B类,那么B类就是A类的内部类。通过上面我所展示的和解释的,我们应该明白以下几点(1)什么是匿名内部类?匿名内部类不是真的没有名字,只是在代码中没有体现出来,在编译时,会单独将他编译成一个类并赋予默认的名字。(2)匿名内部类可以在什么位置?匿名内部类既可以定义在成员位置,也可以定义在局部位置;当我们将匿名内部类定义在成员位置,他就是成员匿名内部类;当我们把它定义在方法体之内,他就是局部匿名内部类。(3)格式的细节。原创 2023-07-14 13:15:00 · 1553 阅读 · 1 评论 -
Java接口与抽象类的区别?
2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的。1. 抽象类可以存在普通成员函数,而接口中只能存在public abstract方法。3. 抽象类只能继承一个,而接口可以实现多个。原创 2023-07-15 13:30:00 · 23 阅读 · 0 评论 -
Java中的Sychronized和ReentrantLock的区别?
(5)sychronized锁的是对象,锁信息保存在对象头中,而ReentrantLock通过代码中的int类型的state标识来标志锁的状态。(2)sychronized会自动的加锁和释放锁,而ReentrantLock需要程序员手动加锁和释放锁。(3)sychronized底层是JVM层面的锁,而ReentrantLock是API层面的锁。(4)sychronized是公平锁,而ReentrantLock可以选择公平锁或非公平锁。(6)sychronized底层有一个锁升级的过程。原创 2023-07-23 11:15:00 · 69 阅读 · 0 评论 -
String字符串相关类底层原理
刚才在第一点我们也说了,String字符串一经创建,值就不可变,当我们在程序编程时,如果对字符串进行拼接,实际上会产生新的字符串,这样不仅会降低程序的执行效率,还会创建出多余无用的字符串垃圾,非常不好。那么有没有更好的解决方案来应对字符串可变化的这一需求呢?当然是有的,它就是我们要说的 StringBuilder。StringBuilder我们可以把它看作是一个容器,创建之后内容是可变的,它可以很大的提高字符串的操作效率。StringBuilder有两个常用的构造方法,如下图所示。原创 2023-07-27 11:00:00 · 236 阅读 · 0 评论 -
static 关键字的用法?
static 是Java语言中一个非常重要的关键字,static 表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量。原创 2023-07-28 13:15:00 · 145 阅读 · 1 评论 -
IO流(1)-字符流与字节流
FileOutputStream 输出流可以把内存中的东西写入到磁盘中去长久保存,其实也可以结合 File InputStream 输入流完成文件的复制操作,思路很简单,我们知道,文件是保存在磁盘中的,我们可以先通过输入流将要复制的文件读取到内存中去,然后再通过输出流写入到硬盘中我们制定好的位置,就能完成文件的复制操作。其实我上面所写的程序,可以复制任何文件,如图片,音频,视频,文件夹,文本文件都可以,因为在计算机底层,所有文件都是以字节的方式存储的,而我们所写的方法正是字节输入流与字节输出流。原创 2023-07-29 14:45:00 · 151 阅读 · 0 评论 -
IO流(2)-缓冲流
我们上贴说到了 FileInputStream,FileOutputStream,FileReader,FileWriter。其实这四个流,我们通常把它叫做原始流,它们是比较偏底层的;而今天我们要说的四个缓冲流,如下图所示,叫包装流,也叫处理流,它们之间也有继承关系自下而上,并且它们都可以提高原始流读写数据的性能。原创 2023-07-30 16:15:00 · 624 阅读 · 0 评论 -
IO流(3)- 转换流与打印流
我们都知道,字符集编码的格式多种多样,有UTF-8,UTF-16,GBK等等很多种,那么在读取的时候也会有差异,例如我们的IDEA编码格式为UTF-8,当我们去读取一个编码格式为GBK的文件时,即便是采用字节流全部读取出来,也会读取到一堆乱码。运行此方法,程序会自动创建名为 test04.txt 的文件,可以看到,这里可以添加诸多内容,证书,字符串,浮点数,布尔类型都可以加入,我们打开文件查看如下,可以看到添加成功。字符转换输出流相比于字符转换输入流,用的就没有那么多了,所以理解即可,但能熟练掌握最好。原创 2023-07-31 15:00:56 · 103 阅读 · 0 评论 -
IO流(4)- 序列化流与反序列化流
如上图所示,序列化流与反序列化流也是IO流中会用到的一种高级流,也是用来包装基本流对象的,它们的继承关系如上图中所示。序列化流是字节流的一种,它负责输出数据。反序列化流也是字节流的一种,它负责输入数据。原创 2023-08-01 11:10:08 · 88 阅读 · 0 评论 -
HashMap 底层源码深度解读
通过上面对源码的解读,我们大致可以得出以下几个结论(1)HashMap默认的初始容量为16;(2)HashMap的最大容量为 2^30;(3)HashMap底层的数据名称为 table;(4)HashMap集合中每个元素成为一个节点,可能是链表节点,也可能是红黑树节点。若是链表节点,存放的数据包括该节点的哈希值,key值,value值,以及下一个结点的内存地址;原创 2023-08-03 14:00:00 · 305 阅读 · 0 评论 -
实现多线程的三种方式
(1)实现多线程有三种方式,一是继承 Thread 类,二是实现 Runnable 接口,三是实现 Callable接口并利用 FutureTask 类接收线程结果。(2)继承 Thread 类实现多线程不可以获取线程的结果;实现 Runnable 接口实现多线程的方式也无法获取返回值结果。(3)我们都知道,继承只能单继承,而接口却可以多实现。因此不难看出,第一种继承 Thread 类实现多线程的方式是不太友好地,虽然编程较为简单,但是可扩展性较差,一旦我们的业务类还需要继承别的类,就不行了。原创 2023-08-04 15:03:31 · 2481 阅读 · 0 评论 -
Java异常体系总结(上篇)
异常其实就是代表程序出现的问题。我们都知道,在编写代码时,我们时常会编写出一些 bug,那么这些 bug,它们有一些可能是异常,有一些可能不是异常。这里有一个误区需要各位注意,学习异常不是为了让我们以后在写代码的过程中不出现异常,但其实也很难避免不出现异常,学习异常是为了让我们知道在程序出现异常之后,该怎么去处理它。2. 异常家族体系介绍我们知道,在Java中,有各种各样的异常,它们其实是一个大的家族,而这个家族的首领就是 java.lung.Throwable。原创 2023-08-07 07:30:00 · 99 阅读 · 0 评论 -
Java异常体系总结(下篇)
可以看到,当我们定义了一个顶级父类异常Exception 之后,IDEA提示我们后面两个异常有错误,点过去 按Alt + Enter键,IDEA提示我们删除此异常,或者将定义的这个数组越界异常放在 Exception 异常之前。原因是什么呢?其实很简单,当我们程序出现问题之后,进入catch语句块,它还是会从上向下执行 catch 语句块,你现在把父类定义在了子类的前面,父类就可以把异常接受,那么子类存在的意义何在呢?原创 2023-08-08 09:00:00 · 88 阅读 · 0 评论 -
Thread 类中常用的成员方法
我们知道,Thread 是Java中已经提供好的一个线程类,那么既然是类,它就会有成员方法,本篇主要讲述一下 Thread 类中常用到的一些成员方法。原创 2023-08-09 11:15:00 · 92 阅读 · 0 评论 -
面向对象的三大基本特征和五大基本原则
而某些时候,实现类型并非需要所有的接口定义,在设计上这是“浪费”,而且在实施上这会带来潜在的问题,对胖接口的修改将导致一连串的客户端程序需要修改,有时候这是一种灾难。当两个模块之间存在紧密的耦合关系时,最好的方法就是分离接口和实现:在依赖之间定义一个抽象的接口使得高层模块调用接口,而底层模块实现接口的定义,以此来有效控制耦合关系,达到依赖于抽象的设计目标。继承基类的方法,并作出自己的改变和/或扩展,子类共性的方法或属性直接使用父类的,而不需要自己定义,只需扩展自己个性化的。核心思想是:依赖于抽象。原创 2023-08-23 10:30:00 · 313 阅读 · 0 评论 -
i++和++i的区别? &和&&的区别? |和||的区别? 三元运算符的执行逻辑?
(2)当我们使用两个 "||" 进行条件判断时,如果左边的判断已经为 true,则就不会进行右边的判断运算,因为此时表达式已经为 true,如果坐标的判断为 false,才会在去执行判断右边的操作;我们知道,++表示自增一,i++和++i都表示使 i 的值自增一,如果单独将它们作为一行代码,它们两个的效果是一样的,当它们参与到运算中,效果就不一样了。可以看到,在最终输出的结果中,使用一个 & 的a和b都自增了1,使用两个 && 的c和d只有c自增了1,这就是一个 & 和两个 && 最大的区别。原创 2023-08-25 14:00:00 · 53 阅读 · 0 评论 -
Java 枚举是什么?什么是枚举类?枚举类的用途?
我们可以从字面意思来理解,枚:一枚一枚的,举:举例,举出,将二者意思结合起来可以理解为一个一个的举出。这样听起来可能有些模糊,我来给大家说一个场景。例如我们定义一个月份类,我们肯定已经确定了该类只有1~12月12个类对象,不会再有别的对象了;还有星期数,只有周一~周日七个类对象,不会有星期八这个对象吧。那么如果我们要将这几个对象全部列出来,可以怎么做呢?首先我们想到的就是创建一个类,然后有几个对象我们就 new 几个对象。原创 2023-09-02 07:00:00 · 646 阅读 · 0 评论 -
浅谈JVM内存模型与GC垃圾回收
Java 虚拟机的底层设计其实是非常复杂的,本篇主要针对JVM的内存模型以及垃圾回收机制做一个简单概括和介绍,明白它各种方法是如何运行的,数据在哪里存放的,以及垃圾回收都有哪些算法是如何使用的。Java 虚拟机是运行在内存中的,当我们的虚拟机拿到了自己可支配的内存之后,它会对这些内存做分配,大致分为五个区域,分别为 栈(JVM栈),堆,本地方法栈,程序计数器,方法区(在JDK8之后改名加元空间)。如下图所示。原创 2023-09-05 10:15:00 · 92 阅读 · 0 评论 -
JDK8的 ConcurrentHashMap 源码分析
总结上面的初始化源码分析,我们可以得到以下结论。(1)ConcurrentHahMap 采用无参构造在底层什么都没有做,真正创建数组是在 put 第一个元素扩容的时候才创建数组的。(2)ConcurrentHashMap 带参构造中如果我们传入的初始容量大于等于最大容量的一半,则实际集合容量会使用最大容量 2^30;如果传入的初始容量小于集合最大长度的一半,则实际计算出的容量是(传入的值 + 传入值的一半 + 1)的结果向上取整并且必须是2的整数次幂。例如传入32,是计算出的容量是64而不是32。原创 2023-09-07 11:45:00 · 119 阅读 · 0 评论 -
怎样理解 Object 类中的 clone() 方法?
所以就有一个问题,我们的代码肯定不能在 java.lang 包下编写,而我们的业务类通常为了能够调用 clone() 去继承实体类,因为可能需要继承其他类,两种办法都行不通,所以我们不许重写父类 Object 中的 clone() 方法,扩大访问权限,才能够调用。基本数据类型是在各自的JVM栈中存储,而引用数据类型则是在堆中存储,JVM栈中的对象保存的不过是堆中对象的内存地址。而且默认重写方法采用的是浅拷贝,如果被克隆对象中含有引用数据类型,只会复制其对象的内存地址,和被克隆的对象操作同一引用数据类型。原创 2023-09-08 12:30:00 · 192 阅读 · 0 评论 -
Java并发基石——CAS是如何实现的?
CAS的全程是 "CompareAndSwap",翻译过来就是 "比较和替换"。CAS的操作包含三个操作数——内存地址,期望值,新值。如果内存位置的值与期望值匹配,那么处理器就会自动将该位置的值更新为新值;否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS可以理解为 "我认为位置V的值应该是A,如果有该值,则将B放在这个位置;否则,不更改该位置的值,只告诉我这个位置现在的值即可"。原创 2023-09-09 14:00:00 · 248 阅读 · 0 评论 -
synchronized 锁的用法
synchronized 的锁对象一定要是唯一的,因为一个线程能不能执行同步代码块,就是要判断该线程是否拥有当前锁对象,如果一个同步代码块的锁对象不是唯一的,有A和B两个锁对象,那么线程1获取到锁对象A去执行同步代码块,线程2获取锁对象B执行同步代码块,就有可能会产生线程冲突,造成线程安全问题。(1)没有线程执行代码块时,锁默认是开放的,一旦有一个线程来执行同步代码块,锁自动关闭,其他线程必须阻塞等待;(2)一个线程在拿到锁执行同步代码块时,只有全部执行完毕线程才会出来,锁会自动释放。原创 2023-09-21 08:00:00 · 78 阅读 · 0 评论 -
Java中的隐式转换和强制转换底层是怎么做的?
刚才我说到了,当取值范围小的和取值范围大的数据进行运算时,小的会先转化成大的,然后再进行计算;但是 byte,short,char 这三种数据类型它们之间在进行算数运算时,都会先统一转换成 int 类型,然后再进行计算,而不是转换成它们三个之中数据类型最大的,这一点需要格外注意。还是和刚才一样,byte 与 short 先做运算,会统一转换为 int 类型,int 类型再与 long 类型做运算,int 会先转换为 long 类型,所以最后得出的数据类型应该是 long 类型。原创 2023-09-22 09:00:00 · 136 阅读 · 0 评论 -
总结 Map 集合哪些 K/V 可以为空?哪些不可以为空?原因是什么?
总结上面四种情况,可以得出如下表图。原创 2023-09-25 10:04:09 · 484 阅读 · 0 评论 -
强引用,弱引用,软引用,虚引用它们有什么区别?你知道吗?
讲解到了这里,各位同学应该对强软弱虚四种引用有一些初步的了解了,那么我们来简单的总结一下吧!强引用:就是不同的引用,平常创建对象的方式就是强引用,被强引用指向的对象不能被垃圾回收器回收。软引用:通过创建软引用类对象来实现,内存足够时允许停留在内存中,内存不够时就将其从内存中清除给其他对象腾出空间,可以作为缓存来使用。软引用:比强引用弱,就算有引用指向它,只要发生GC垃圾回收过程,软引用对象就会被清除。虚引用:比弱引用还要若,通常用作管理对外内存。原创 2023-09-26 10:46:48 · 1023 阅读 · 3 评论 -
深挖 ThreadLocal 底层原理?它有什么用?学会之后手撕面试官
经过上面三点的说明,我画了一个的简化图,(1)程序中我们 new 一个 ThreadLocal 对象用 tl 接收,也可以 new 多个;(2)每个线程内部都有一个 tls 属性指向独属于自己的那个 Map 集合;(3)当我们调用 tl 对象 set 方法的时候,实际上底层会创建一个 Entry 键值对对象,K是 set 方法的调用者 tl,V 则是我们要保存的 value 值;(4)在进行 set 存放操作的时候底层创建的 Entry 对象则是弱引用类型,存放在 Map 集合中。原创 2023-09-27 18:05:46 · 604 阅读 · 0 评论 -
谈谈你对 finalize 方法的理解,该怎样回答才能体现出高水平?浮于表面的答案永远不行!
如果我们重写了 finalize 方法,那么对象在变成垃圾被垃圾回收器回收之前,需要先执行 finalize 方法,而 finalize 方法并不是由垃圾回收器来调用的,是有一个专门的线程叫 finalizer 来调用的,finalizer 线程内部有一个引用队列,垃圾回收器识别到垃圾对象之后,会把该对象添加到引用队列中去,finalizer 线程会依次调用每个对象的 finalize 方法然后进行清理。原创 2023-10-07 14:34:52 · 67 阅读 · 0 评论 -
你真的懂Java的继承吗?你知道什么时候用继承吗?设计继承是为了什么?
OK,下面我们几句句话来总结上面四个例子得出的结论。(1)在继承中,方法调用变量时会采用就近原则,当方法想要访问的变量方法内部本身就有时,会最优先访问方法内部的局部变量;(2)当方法内部访问不到变量时,会去方法当前类成员变量中寻找访问;(3)如果成员变量中也访问不到时,会最后去父类成员变量访问;(4)如果想要主动访问当前方法类成员变量,可以通过 this 关键字,如果想要调用父类成员变量,则可以通过 super 关键字。原创 2023-10-10 14:42:29 · 313 阅读 · 0 评论 -
Lambda 表达式使用详解,一篇文章手把手教会你
记住一句话就可以了,"有且仅有一个抽象方法的接口叫函数式接口,接口上可以添加@FunctionalInterface注解"。例如我们刚才使用的 Compartor 接口,它就是一个函数式接口,我们看一下它的源码就可以知道,如下图所示,接口上就标注有 @FunctionalInterface 注解。原创 2023-10-11 11:24:14 · 715 阅读 · 0 评论 -
别再使用循环的方式筛选元素了!开发常用的Stream流+Lambda表达式过滤元素了解过吗?10000字超详细解析
如下所示,参数可以为 字符串,整型,浮点型,这些零散不统一的数据,但是,这种方式几乎在开发中根本不会用,我们不会吧数据类型不一致的数据放在一起,所以自己敲代码的时候玩玩就可以了,这种 获取 stream 流的方式了解即可,concat 合并两个流的方法,我调用此方法的时候,建议两个要合并的流存放相同类型的数据,如果存放的不相同,那么合并后的流存放的类型就两个流数据类型的父类,可能会导致原来自己独有的方法无法被调用,这一点要注意。原创 2023-10-12 10:35:20 · 1370 阅读 · 0 评论 -
String 字符串不可变带来的好处是什么?
String 虽然是在堆中,但其实分为两种情况,如果我们使用 String string = "xxx" 的方式来创建字符串,那么被创建出来的字符串对象是存放在堆中的字符串常量池中的,可以重复利用;所以说,String 虽然不可变,却可以重复利用,在开发过程中,几乎都是使用 String str = "xxx" 创建字符串,然后创建的字符串会被缓存到堆中的字符串常量池中,在同一各项目中不管有多少个人创建字符串,只要字符串内容一样,其实最后都是用的常量池中的同一个字符串对象,大大的降低了内存的消耗。原创 2023-10-30 16:27:27 · 331 阅读 · 0 评论 -
从源码深度剖析 CopyOnWriteArrayList 线程安全集合,一起来看看吧
使用过 ArrayList 集合的同学应该大致都知道,ArrayList 是一个非线程安全的集合;同样,Java也为我们提供了线程安全的 List 集合,只是用的频率没有 ArrayList 那么频繁,它就是我们本篇文章要说的 CopyOnWriteArrayList。CopyOnWriteArrayList 的原理不难理解它底层采用了加锁的方式保证线程安全并且加的是 Lock 锁而不是 Sychonized 锁。原创 2023-10-31 14:56:12 · 199 阅读 · 0 评论