目录
Java基础
java中的Math.round(-1.5)等于多少?
JDK和JRE的区别?
抽象类能被final修饰吗?
如何决定使用TreeMap还是HashMap?
迭代器Iterator是什么?
Queue中的poll和remove有什么区别?
为什么要使用克隆,如何实现克隆?
红黑树
IO流
int是几个字节?
String长度限制
继承和实现的区别?为什么不支持多继承?
int和Integer有什么区别?
HashMap和ConcurrentHashMap有什么区别?
什么时候使用抽象类?什么时候使用接口?
try、catch、finally中各有一个return,最后会返回哪个块的return?
静态方法和普通方法的区别?
BIO、NIO、AIO的区别
Java装箱缓存机制
Java创建对象几种方式
final有哪些用法?
3*0.1 == 0.3返回值是什么
计算机网络
什么是CSRF攻击,如何避免?
TCP协议为什么要三次握手而不是两次?
TCP粘包拆包
长连接的好处和坏处?
反向代理是什么?
TCP的可靠性传输怎么保证?
DNS寻址
JVM
jvm怎么创建一个对象?
finalize方法
可达性分析算法GC ROOT
堆栈分配比例
垃圾回收器
JUC并发编程
在 java 中 wait 和 sleep 方法的不同?
ThreadLocal父线程和子线程的数据传递?
AQS与Synchronized的区别
线程池拒绝策略
MySQL
MySQL 左连接和右连接有什么区别?内连接没有匹配上会怎么?
一条SQL的执行过程是怎样的
MyBatis
#{}和${}的区别是什么?
Mybatis执行流程
延迟加载
Redis
Redis如何扫描前缀相同的key?Redis的keys和scan有什么区别?
延迟双删
RDB 持久化会阻塞主线程吗?
MQ
RocketMQ和Kafka有什么区别?
RocketMQ的重试机制?
Springcloud
Nacos和Euruka的区别?
Nacos怎么保证数据一致性的?
Java基础
java中的Math.round(-1.5)等于多少?
Math的round方法是四舍五入,如果参数是负数,则往大的数如,Math.round(-1.5)=-1,如果是Math.round(1.5)则结果为2
JDK和JRE的区别?
JDK 是 Java Development ToolKit 的简称,也就是 Java 开发工具包。JDK 是整个 Java 的核心,包括 Java 运行环境(Java Runtime Envirnment,简称 JRE),Java 工具(比如 javac、java、javap 等等),以及 Java 基础类库(比如 rt.jar)。针对 Java 程序的开发者来说。
JRE:Java程序运行所需的环境,提供了运行Java程序所需的基础设施,如Java虚拟机(JVM)和Java类库,但不包含开发工具。
抽象类能被final修饰吗?
不能
如何决定使用TreeMap还是HashMap?
需要保持键(Key)的一个有序状态,则应该选择 TreeMap
。TreeMap
内部基于红黑树实现,可以保持键的自然顺序或者根据构造器提供的 Comparator
进行排序。如果键的排序不是必须的,使用 HashMap
会更好,因为它的操作通常更快。
TreeMap示例:
TreeMap<Integer, String> treeMap = new TreeMap<>();// 添加键值对treeMap.put(3, "Three");treeMap.put(1, "One");treeMap.put(2, "Two");for (Map.Entry<Integer, String> entry : treeMap.entrySet()) {System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());}//Key: 1, Value: One
//Key: 2, Value: Two
//Key: 3, Value: Three
迭代器Iterator是什么?
Java迭代器(Iterator)是 Java 集合框架中的一种机制,是一种用于遍历集合(如列表、集合和映射等)的接口。它提供了一种统一的方式来访问集合中的元素,而不需要了解底层集合的具体实现细节。
ArrayList<Integer> numbers = new ArrayList<Integer>();numbers.add(12);numbers.add(8);numbers.add(2);numbers.add(23);Iterator<Integer> it = numbers.iterator();while(it.hasNext()) {Integer i = it.next();if(i < 10) {it.remove(); // 删除小于 10 的元素}}System.out.println(numbers);
Queue中的poll和remove有什么区别?
Queue<String> queue = new LinkedList<>();queue.offer("Apple");queue.offer("Banana");System.out.println("Poll method: " + queue.poll()); // 输出 "Apple",队列变为 ["Banana"]System.out.println("Poll method on empty: " + queue.poll()); // 输出 "Banana",队列变为空System.out.println("Poll method on empty again: " + queue.poll()); // 输出 null,因为队列已空// 如果此时使用 remove(),将抛出 NoSuchElementException// System.out.println("Remove method on empty: " + queue.remove()); // 会抛出异常
为什么要使用克隆,如何实现克隆?
JAVA对象克隆(为什么,如何实现,浅克隆和深克隆,解决多层克隆问题)_java 复杂的对象克隆-CSDN博客
代码示例:
public class CloneDemo {public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {Person p1 = new Person();p1.setName("张三");p1.setAge(18);Address address = new Address();address.setCity("北京");p1.setAddress(address);// 浅克隆 p1 对象
// Person p2 = p1.clone();
// System.out.println(p1 == p2); // false
// System.out.println(p1.getAddress() == p2.getAddress()); // true// 序列化ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(p1);// 将流序列化成对象ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);Person p2 = (Person) ois.readObject();System.out.println(p1 == p2); // falseSystem.out.println(p1.getAddress() == p2.getAddress()); //false}
}
class Person implements Cloneable,Serializable {private String name;private int age;private Address address; // 引用类型@Overridepublic Person clone() throws CloneNotSupportedException {return (Person) super.clone();}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 Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}}class Address implements Serializable {private String city;public String getCity() {return city;}public void setCity(String city) {this.city = city;}}
红黑树
IO流
int是几个字节?
4字节
String长度限制
理论上的限制:
- 在 Java 8 及更早版本中,
String
的长度由char[]
数组的最大长度限制,char[]
数组的索引为整数(int
),最大值为Integer.MAX_VALUE - 1
(因为数组需要一个额外的空间来表示数组结束)。这个值大约是 2^31 - 2(即 2147483646)。
继承和实现的区别?为什么不支持多继承?
Java只支持“接口”的多继承,不支持“类“”的多继承;而继承在java中具有单根性,子类只能继承一个父类。
某个接口被类实现时,在类中一定要实现接口中的抽象方法;而继承想调用那个方法就调用那个方法。
多继承可能导致命名冲突,因为两个或多个父类可能有相同的方法名和属性,这种情况下,编译器需要确定使用哪个类的实现,可能导致意料之外的结果。
int和Integer有什么区别?
- 数据类型不同:int 是基础数据类型,而 Integer 是包装数据类型;
- 默认值不同:int 的默认值是 0,而 Integer 的默认值是 null;
- 内存中存储的方式不同:int 在内存中直接存储的是数据值,而 Integer 实际存储的是对象引用,当 new 一个 Integer 时实际上是生成一个指针指向此对象;
- 实例化方式不同:Integer 必须实例化才可以使用,而 int 不需要;
- 变量的比较方式不同:int 可以使用 == 来对比两个变量是否相等,而 Integer 一定要使用 equals 来比较两个变量是否相等;
- 泛型使用不同:Integer 能用于泛型定义,而 int 类型却不行。
HashMap和ConcurrentHashMap有什么区别?
- HashMap:HashMap 允许使用 null 作为值和键。
- ConcurrentHashMap:ConcurrentHashMap 不允许使用 null 作为键,但允许使用 null 作为值。
什么时候使用抽象类?什么时候使用接口?
何时使用抽象类?何时使用接口?_什么时候用抽象类什么时候用接口-CSDN博客
什么时候使用接口?什么时候使用抽象类?
使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。
抽象类适合用来定义某个领域的固有属性,也就是本质,接口适合用来定义某个领域的扩展功能。
一、什么时候使用抽象类?
当2个或多个类中有重复部分的时候,我们可以抽象出来一个基类,如果希望这个基类不能被实例化,就可以把这个基类设计成抽象类。
当需要为一些类提供公共的实现代码时,应优先考虑抽象类 。因为抽象类中的非抽象方法可以被子类继承下来,使实现功能的代码更简单。
抽象类只能是单继承的,不能多继承。
二、什么时候使用接口?
当注重代码的扩展性跟可维护性时,应当优先采用接口。
①接口与实现它的类之间可以不存在任何层次关系,接口可以实现毫不相关类的相同行为,比抽象类的使用更加方便灵活;
②接口只关心对象之间的交互的方法,而不关心对象所对应的具体类。接口是程序之间的一个协议,比抽象类的使用更安全、清晰。一般使用接口的情况更多。
try、catch、finally中各有一个return,最后会返回哪个块的return?
最后会返回finally中的。
静态方法和普通方法的区别?
- 静态方法是属于类的,而普通方法是属于对象的。因此,静态方法可以在不创建对象的情况下直接调用,而普通方法则需要先创建对象,然后通过对象来调用。
- 静态方法不能访问非静态成员变量,而普通方法即可访问静态成员变量有可以访问非静态成员变量。
BIO、NIO、AIO的区别
Java装箱缓存机制
Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 -128,127 的相应类型的缓存数据,Character 创建了数值在 0,127 范围的缓存数据,Boolean 直接返回 True or False(内部指向静态变量)
Java创建对象几种方式
new创建新对象
通过反射机制
采用clone机制
通过序列化机制
final有哪些用法?
被final修饰的类不可以被继承
被final修饰的方法不可以被重写
被final修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变
3*0.1 == 0.3返回值是什么
false,因为有些浮点数不能完全精确的表示出来
计算机网络
什么是CSRF攻击,如何避免?
CSRF(Cross-Site Request Forgery)攻击是一种常见的网络安全漏洞,它利用了网站对用户浏览器的信任,以用户的身份在用户不知情的情况下执行恶意操作。
CSRF攻击的过程如下:
1.用户登录受信任的网站A,并在本地生成会话Cookie。
2.在未注销网站A的情况下,用户在浏览器中访问了恶意网站B。
3.恶意网站B中的攻击者的代码会发起请求,利用用户在网站A的身份进行操作。这些请求可以是执行任意操作,如更改密码、发表言论、转账等。
随机令牌(CSRF Token):网站可以在每个用户会话中生成一个唯一的令牌,并将其嵌入到用户请求的表单或URL参数中。在处理请求时,服务器会验证令牌的有效性。攻击者无法获取用户的令牌,因此无法通过恶意网站发起有效的请求。
TCP协议为什么要三次握手而不是两次?
如果只有两次握手,客户端发送连接请求,但在网络中由于某种原因延迟。此时,客户端可能认为连接未建立,因此发送新的连接请求。如果服务器接收到了两个连接请求,并回应确认,就会建立两个相互独立的连接。这可能导致资源浪费和数据混乱。通过引入第三次握手,可以确保服务器收到重复的连接请求时能够正确处理,避免重复连接的建立。通过三次握手,TCP协议可以建立一种可靠的连接机制,确保双方都知道连接已建立,并避免了一些潜在的问题。这种连接建立方式能够提供可靠的数据传输和错误检测,是TCP协议可靠性的基础。
TCP粘包拆包
TCP中的粘包、拆包问题产生原因及解决方法_tcp 粘包/拆包的原因及解决方法-CSDN博客
长连接的好处和坏处?
长连接优点:
- 避免了重复创建和销毁连接。
- 提高传输效率。
- 实现实时传输。
- 节省了系统资源的浪费。
长连接缺点:
- 占用了更多的资源。
- 增加了服务器的压力。
- 对网络环境的要求是比较高。
反向代理是什么?
反向代理定义:用于客户端和服务器端进行通讯,代理服务器端的一种代理,可以隐藏真实的服务器地址。反向代理的经典实现就是 Nginx。 优点:
- 反向代理服务器可以有缓存,增加查询的效率。
- 可以实现负载均衡,从而提升服务器的 QPS,实现服务器的水平扩展。
- 反向代理通常自带健康检查机制,可以帮你正确的访问健康的服务实例。
- 隐藏真实服务器的地址,一定程度的保证了服务器的安全性。
TCP的可靠性传输怎么保证?
- 确认应答。
- 超时重传。
- 连接管理(三次握手和四次挥手)
DNS寻址
JVM
jvm怎么创建一个对象?
JVM 类加载可以分为以下几个阶段:
- 加载
- 链接
- 验证
- 准备
- 解析
- 初始化
具体内容如下。
① 加载
加载(Loading)阶段是整个“类加载”(Class Loading)过程中的一个阶段,它和类加载 Class Loading 是不同的,一个是加载 Loading 另一个是类加载 Class Loading,所以不要把二者搞混了。 在加载 Loading 阶段,Java 虚拟机需要完成以下 3 件事:
- 通过一个类的全限定名来获取定义此类的二进制字节流;
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
- 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。
② 验证
验证是连接阶段的第一步,这一阶段的目的是确保 Class 文件的字节 流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信 息被当作代码运行后不会危害虚拟机自身的安全。 验证选项:
- 文件格式验证
- 字节码验证
- 符号引用验证...
③ 准备
准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段。 比如此时有这样一行代码:
public static int value = 123;
它是初始化 value 的 int 值为 0,而非 123。
④ 解析
解析阶段是 Java 虚拟机将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。
⑤ 初始化
执行静态代码块和静态字段的初始化表达式:这些操作是按照它们在类中出现的顺序来执行的。
finalize方法
对象中存在一个方法【finalize】。当对象被标记为可回收后,当发生GC时,首先会判断这个对象
是否执行了finalize方法,如果这个方法还没有被执行的话,那么就会先来执行这个方法,接着在这个方法执行中,可以设置当前这个对象与GC ROOTS产生关联,那么这个方法执行完成之后,GC会再次判断对象是否可达,如果仍然不可达,则会进行回收,如果可达了,则不会进行回收。finalize方法对于每一个对象来说,只会执行一次。如果第一次执行这个方法的时候,设置了当前对象与RC ROOTS关联,那么这一次不会进行回收。 那么等到这个对象第二次被标记为可回收时,那么该对象的finalize方法就不会再次执行了。
可达性分析算法GC ROOT
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中 JNI(即一般说的 Native 方法)引用的对象
堆栈分配比例
新生代:老年代 1:2 Eden区,S0区,S1区【8:1:1】每个线程默认会开启1M的栈
垃圾回收器
串行垃圾收集器
Serial和Serial Old串行垃圾收集器,是指使用单线程进行垃圾回收,堆内存较小,适合个人电脑
Serial 作用于新生代,采用复制算法,Serial Old 作用于老年代,采用标记-整理算法,垃圾回收时,只有一个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。
并行垃圾收集器
Parallel New和Parallel Old是一个并行垃圾回收器,JDK8默认使用此垃圾回收器,Parallel New作用于新生代,采用复制算法,Parallel Old作用于老年代,采用标记-整理算法,垃圾回收时,多个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。
CMS(并发)垃圾收集器
CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,是一款以获取最短回收停顿时间为目标的收集器,停顿时间短,用户体验就好。其最大特点是在进行垃圾回收时,应用仍然能正常运行。
JUC并发编程
在 java 中 wait 和 sleep 方法的不同?
ThreadLocal父线程和子线程的数据传递?
父线程生成的变量需要传递到子线程中进行使用,那么在使用ThreadLocal似乎就解决不了这个问题,ThreadLocal有一个子类InheritableThreadLocal就是为了解决这个问题而产生的,使用这个变量就可以轻松的在子线程中依旧使用父线程中的本地变量。
ThreadLocal<String> ThreadLocal = new ThreadLocal<>();ThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();ThreadLocal.set("父线程数据:threadLocal");inheritableThreadLocal.set("父线程数据:inheritableThreadLocal");new Thread(()->{System.out.println("子线程获取父类ThreadLocal数据:" + ThreadLocal.get());System.out.println("子线程获取父类inheritableThreadLocal数据:" + inheritableThreadLocal.get());}).start();
参考链接:父子线程之间值传递解决方案:InheritableThreadLocal和TransmittableThreadLocal_threadlocal 父子线程传参怎么解决-CSDN博客
AQS与Synchronized的区别
AQS常见的实现类
ReentrantLock 阻塞式锁
Semaphore
信号量
CountDownLatch 倒计时锁
线程池拒绝策略
MySQL
MySQL 左连接和右连接有什么区别?内连接没有匹配上会怎么?
- 左连接:左连接是以左边的表格(也称为左表)为基础,将左表中的所有记录和右表中匹配的记录联接起来。即使右表中没有匹配的记录,左连接仍然会返回左表中的记录。如果右表中有多条匹配记录,则会将所有匹配记录返回。左连接使用
LEFT JOIN
关键字来表示。 - 右连接:右连接是以右边的表格(也称为右表)为基础,将右表中的所有记录和左表中匹配的记录联接起来。即使左表中没有匹配的记录,右连接仍然会返回右表中的记录。如果左表中有多条匹配记录,则会将所有匹配记录返回。右连接使用
RIGHT JOIN
关键字来表示。 - 内连接使用的是 inner join 关键字来实现的,它会匹配到两张表的公共部分
一条SQL的执行过程是怎样的
MyBatis
#{}和${}的区别是什么?
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
SQL注入其中一个场景:
String sql = "select * from order where id = " + id,如果id = 订单号没问题,如果id = " 10 or 1 = 1"这样就会发生问题,把所有的订单查询出来,这就是SQL注入。
Mybatis执行流程
延迟加载
延迟加载的意思是:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。
Redis
Redis如何扫描前缀相同的key?Redis的keys和scan有什么区别?
Redis Scan 命令用于迭代数据库中的数据库键。
SCAN 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
SCAN 返回一个包含两个元素的数组, 第一个元素是用于进行下一次迭代的新游标, 而第二个元素则是一个数组, 这个数组中包含了所有被迭代的元素。如果新游标返回 0 表示迭代已结束。
相关命令:
- SSCAN 命令用于迭代集合键中的元素。
- HSCAN 命令用于迭代哈希键中的键值对。
- ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)。
Redis 查询前缀相同的 Key 实现方式:
- keys -> keys user*。
- scan -> scan 0 math user* count 100。
keys 查询所有的匹配数据,scan 是可以查询部分数据。
延迟双删
延迟双删指的是删除两次缓存(并且最后一次是延迟删除),具体执行流程如下:
- 删除缓存
- 更新数据库
- 延迟一会再删除缓存
最后一次延迟删除缓存的原因是,为了避免上面因为并发问题导致保存旧值的情况发生,所以会延迟一段时间之后再进行删除操作。
RDB 持久化会阻塞主线程吗?
因为 RDB 持久化是有可能会阻塞主线程的,因为 RDB 持久化有以下两种命令:
- save:同步持久化 Redis。
- bgsave:background save,后台保存的意思,也就是后台持久化 Redis。
默认情况下,如果不是手动执行“bgsave”命令,则会使用“save”命令来持久化 Redis,此时是会阻塞 Redis 主线程的。
MQ
RocketMQ和Kafka有什么区别?
1. RocketMQ 本身支持死信队列、延迟队列;Kafka 本身不支持死信队列、延迟队列。
2. 存储形式:Kafka采用partition,每个topic的每个partition对应一个log文件,一个log文件分成了多个Segment段,RocketMQ采用CommitLog+ConsumeQueue,单个broker所有topic在CommitLog中顺序写,同时每个topic下的每个queue都有一个对应的ConsumeQueue文件作为索引。
3. 存储可靠性:
- RocketMQ支持异步刷盘,同步刷盘,同步Replication,异步Replication。
- Kafka使用异步刷盘,异步Replication。
RocketMQ的重试机制?
- 生产者重试:生成者发送消息的类型有同步发送、异步发送、单次发送(oneway),但模式为同步发送、异步发送才有消息重试机制。
- 消费者重试:消费者模式有广播模式和集群模式;广播模式不会进行消息重试,它只会记录警告信息;集群模式会进行消息重试(通过延迟任务来实现消息重试,默认情况下如果重试超过 16 次就会将此消息存到死信队列)
Springcloud
Nacos和Euruka的区别?
- 功能上不同:Nacos 既提供注册中心又提供配置中心;Euruka 只有注册中心。
- 通讯方式不同:Nacos 通讯方式是依靠 Netty 实现的长连接;Euruka 短连接+定时任务。
- CAP 理论支持不同:Nacos 默认是 AP 模式,但它支持手动设置 CP 模式;Euruka 只支持 AP 模式。
- 健康检查机制不同:Nacos 健康检查机制(默认临时实例),每 5s 上报一次健康状况;15s 未上报任务不健康;30s 会剔除此实例;Euruka 健康检查机制,每 30s 上报一次健康状况;60s 未收到认为不健康;90s 未收到剔除此实例。
Nacos怎么保证数据一致性的?
Nacos 通过 Raft 实现 Leader 节点的选举,由 Leader 节点将数据同步给所有的普通节点,以保证数据的一致性的。