目录
9、new String("a") + new String("b") 会创建几个对象
33、Collection 和 Collections 区别
39、ArrayList和LinkedList查询之间的区别?
44、在 Queue 中 poll()和 remove()有什么区别?
51、Java8开始ConcurrentHashMap,为什么舍弃分段锁?
52、ConcurrentHashMap(JDK1.8)为什么要使用synchronized而不是如ReentranLock这样的可重入锁?
53、concurrentHashMap和HashTable有什么区别
55、请谈谈 ReadWriteLock 和 StampedLock
57、为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
60、为什么 wait(), notify()和 notifyAll()必须在同步方法或者同步块中被调用?
64、请谈谈 volatile 有什么特点,为什么它能保证变量对所有线程的可见性?
65、为什么说 Synchronized 是一个悲观锁?乐观锁的实现原理又是什么?什么是 CAS,它有什么特性?
67、请尽可能详尽地对比下 Synchronized 和 ReentrantLock 的异同。
70、跟 Synchronized 相比,可重入锁 ReentrantLock 其实现原理有什么不同?
77、线程池中的线程是怎么创建的?是一开始就随着线程池的启动创建好的吗?
79、既然 volatile 能够保证线程间的变量可见性,是不是就意味着基于 volatile 变量的运算就是并发安全的?
81、请谈谈 ThreadLocal 是怎么解决并发安全的?
82、很多人都说要慎用 ThreadLocal,谈谈你的理解,使用 ThreadLocal 需要注意些什么?
85、多线程中 synchronized 锁升级的原理是什么?
86、synchronized 和 ReentrantLock 区别是什么?
87、Java Concurrency API 中的 Lock 接口(Lock interface)是什么?对比同步它有什么优势?
97、http 响应码 301 和 302 代表的是什么?有什么区别?
108、什么是设计模式?你是否在你的代码里面使用过任何设计模式?
109、Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
110、在 Java 中,什么叫观察者设计模式(observer design pattern)?
113、举一个用 Java 实现的装饰模式(decorator design pattern)?它是作用于对象层次还是类层次?
114、什么是 Spring 框架?Spring 框架有哪些主要模块?
118、BeanFactory 和 ApplicationContext 有什么区别?
123、Spring Bean 的作用域之间有什么区别?Spring容器中的bean可以分为5个范围:
124、如何在 Spring Boot 中禁用 Actuator 端点安全性?
126、Spring 框架中的单例 Beans 是线程安全的么?
130、spring mvc 和 struts 的区别是什么?
137、请举例说明如何在 Spring 中注入一个 Java Collection?
139、mybatis 是否支持延迟加载?延迟加载的原理是什么?
142、mybatis 和 hibernate 的区别有哪些?
146、hibernate 中如何在控制台查看打印的 sql 语句?
148、hibernate 实体类可以被定义为 final 吗?
149、在 hibernate 中使用 Integer 和 int 做映射有什么区别?
150、什么是 Spring Boot?Spring Boot 有哪些优点?
161、什么是 Swagger?你用 Spring Boot 实现了它吗?
163、一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
177、RabbitMQ有哪些重要的角色?有哪些重要的组件?
189、新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
1、JDK 、JRE 、JVM 关系
jdk:Java的开发工具包
jre:Jdk开发环境
jvm:是运行java字节码文件的虚拟计算机
关系:JDK包含JRE,JRE又包含JVM,如图所示,其中jvm可以实现夸平台操作。
2、== 和 equals 区别
== | equals | |
基本数据类型 | 比较的是值 | ----- |
引用数据类型 | 比较的是地址 | 比较的是内容 |
==:比较的是内存空间的地址是否一致;
equals:常用来比较字符串,比较的内存空间的内容是否一致;
备注:equals继承的是object类,里面的equale的方法返回仍然是“==”,所以在对象重写equals情况下,会返回比较的内容,详细见equals的重写代码。
@Override public boolean equals(Object o) { // 比较引用地址 if (this == o) return true; // 比较对象是否为null if (o== null) return false; // 校验o是否是一个实例 if (!(o instanceof Student)) return false; Student student = (Student) o; return // o是一个实例,比较内容 Objects.equals(name, student.name); }
3、final 作用
- 修饰类,表示最终类,无法被继承;
- 修饰方法,表示最终的方法,子类无方法被重写,但可以被继承;
- 修饰基本数据类型,如int,表示常量;
- 修饰引用数据类型,表示的地址不可变;
4、Math的取整方法
- ceil:向上取整: Math.ceil(10.6) = 11;
- floor:向下取整; Math.ceil(10.6) = 10;
- round:四舍五入;Math.round(11.6) = 12;
5、基础的数据类型
byte、short、char、int、long、double、float、boolean
6、jvm内存模型
栈:各种方法、局部变量(先入后出)
堆:new的对象
方法区:类加载器classLoader 可以存常量、编译的缓存信息、各个类,初始化加载的时候留存空间,像静态变量
String.intern()方法的功能:其功能手动将字符串放入常量池中
public static void main(String[] args) {
String s3 = new String("ABC");
String s4 = new String("ABC");
String s1 = "ABC";
String s2 ="AB" + "C";
String s5 = "ABC";
String s6 ="AB" ;
String s7 =s6 + "C" ;
System.out.println(s1 == s2);//true s1进入常量池,s2编译后引用常量池的对象
System.out.println(s3 == s4); //false 堆的两个地址
System.out.println(s3.equals(s4)); //true 比较内容
System.out.println(s1==s5); //true s1进入常量池,s5进入常量池,s1和s5引用同一个对象
System.out.println(s1==s3); //false s1进入常量,s3堆内存创建对象,s1和s3引用不同对象
System.out.println(s1.equals(s3));//true 比较内容
System.out.println(s1==s7);//false s1,s6常量池对象,s7堆创建对象,s1和s7引用不同对象
}
7、字符串反转
StringBuilder
public static void main(String[] args) {
String s1 = "ABC";
StringBuilder builder = new StringBuilder();
String s3 = builder.append(s1).reverse().toString();
System.out.println(s3);
}
遍历
public static void main(String[] args) {
String s1 = "ABCC BA";
String[] split = s1.split("");
String[] xx = new String[split.length];
for (int i = split.length-1; i >=0; i--) {
xx[i] = split[split.length-i-1];
}
// 使用空字符将逆序后的字符数组连接成一个字符串
String join = String.join("", xx);
System.out.println(join);
}
递归
public static void main(String[] args) {
String s1 = "ABCDEFG";
System.out.println(XXController.reverseNumber(s1));
}
public static String reverseNumber(String str){
if (StringUtils.isBlank(str) || str.length()==1){
return str;
}
return reverseNumber(str.substring(1)) + str.charAt(0);
}
8、String 类的常用方法
public static void main(String[] args) {
String str = "ABCDEFGA";
// 1.返回第一个C位置的索引, 没有就返回-1,有就返回索引
int c = str.indexOf("C");
System.out.println(c);//2
// 2.获取索引为2位置的字符
char c1 = str.charAt(2);
System.out.println(c1);//C
// 3.截取包括C之后的字符串
String c2 = str.substring(2);
System.out.println(c2);//CDEFGA
// 4.截取BCD
String c3 = str.substring(1,4);
System.out.println(c3);//BCD
// 5.是否包含C
boolean c4 = str.contains("C");
System.out.println(c4);//true
// 6.字符串是否以A开头
boolean c5 = str.startsWith("A");
System.out.println(c5);//true
// 7.替换字符串的C为“牛”
String c6 = str.replace("C", "牛");
System.out.println(c6);//AB牛DEFGA
}
9、new String("a") + new String("b") 会创建几个对象
1 .拼接字符串 StringBuilder 对象
2 .创建 a 的String 对象
3 .常量池中放入 “a”
4 .创建 b 的String 对象
5 .常量池中放入 “b”
6 .拼接的结果生成一个 String 对象
10、重写和重载区别
重写:overriding 发生在继承中,方法名、返回值、参数必须一致,但是可以改变方法提的内容,注意不能抛出新的异常。
重载:overloading发生在一个类中,参数不同的相同方法,参数可以是个数不同、类型不同、顺序不同。
11、接口、普通、抽象区别
抽象类有构造函数,有普通方法和抽象方法,不能实例化,其子类继承必须重写父类的所有抽象方法。
普通类:有构造函数,没有抽象方法,可以单继承
接口:没有构造函数,成员变量默认为最终量public static final。方法都是抽象方法。多实现
12、IO 流
基于计算机对程序的输入和输出操作,输入输出的操作时基于流进行。
数据源:硬盘、数据库系统、硬件系统、网络上的某个内容等等(可以称之为‘外部系统’)。
程序:计算机进行操作的指令(可以通过知指令实现一些内容,例如打开下载的某个文件)
io流的存储方式:内存IO、网络IO和磁盘IO
IO流分类:
1.流向:输入流和输出
输入流(InputStream):读取程序的外部数据。
输出流( OutPutStrea):将数据写到外部系统。
2.处理数据单位:
字节流(FilelnputStream、FileOutputStream):8位字节,可以处理一切数据;没有缓冲区,处理速度比字符流快。
字符流(FileReader、FileWriter):16位字节,只能处纯文本;带有缓冲区。
3.处理对象
节点流:可以直接从数据源或目的地读写数据,如FileInputStream、FileOutputStream、FileReader、FileWriter、.DatalnputStream等。
处理流:不直接连接到数据源或目的地。通过对其他流的处
理提高程序的性能,如BufferedInputStream[缓冲输入流]、BufferedReader[缓冲输出流]等。处理流也叫包装流。
13、BIO、NIO、AIO 区别
同步阻塞的BIO:数据的读取写入必须在一个线程内等待完成
同步非阻塞的NIO、
异步非阻塞的AIO
同步与异步
同步: 同步就是发起一个调用后,被调用者未处理完请求之前,调用不返回。
异步: 异步就是发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但是被调用者并没有返回结果,此时我们可以处理其他的请求,被调用者通常依靠事件,回调等机制来通知调用者其返回结果。
同步和异步的区别最大在于异步的话调用者不需要等待处理结果,被调用者会通过回调等机制来通知调用者其返回结果。
阻塞和非阻塞
阻塞: 阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。
非阻塞: 非阻塞就是发起一个请求,调用者不用一直等着结果返回,可以先去干其他事情。
那么同步阻塞、同步非阻塞和异步非阻塞又代表什么意思呢?
你妈妈让你烧水,小时候你比较笨啊,在哪里傻等着水开(同步阻塞)。
等你稍微再长大一点,你知道每次烧水的空隙可以去干点其他事,然后只需要时不时来看看水开了没有(同步非阻塞)。
后来,你们家用上了水开了会发出声音的壶,这样你就只需要听到响声后就知道水开了,在这期间你可以随便干自己的事情,你需要去倒水了(异步非阻塞)。
14、反射
反射是在运行状态中,对于任意一个类和对象,都能够知道所有属性和方法;
15、情况下需要序列化
序列化定义:将对象中的数据编码为字节序列的过程,可以理解为将对象流化。
- 对象序列化,将对象中的数据编码为字节序列的过程。
- 反序列化;将对象的编码字节重新反向解码为对象的过程。
什么情况下需要序列化:要明白序列化是将对象通过流的形式进行转换,程序运行停止的时候,同样对象也会消失,这时候可以通过序列化,将数据写入到磁盘中保存。
对象序列化注意:实现serializable接口,建议在类中添加序列化版本号。
16、克隆、深拷贝和浅拷贝区别
克隆:包括浅拷贝和深拷贝。
浅拷贝是指复制对象数据,生成这个对象的一个新的对象;
深拷贝是只在浅拷贝的基础上,通过拷贝均在新复制的对象上面进行操作。
实现方式:
1.对象上实现Cloneable接口,重写clone方法(深拷贝和浅拷贝的实现方式不同)。
注意:BeanUtils,apache和Spring都提供了bean工具,只是这都是浅克隆。
2.实现Serializable接口,对象的序列化和反序列化实现克隆,可以实现真正的深克隆。// 浅拷贝 @Override public Object clone() throws CloneNotSupportedException { Object object = super.clone(); return object; }
// 深拷贝 @Override protected Object clone() throws CloneNotSupportedException { Person person= (Person) super.clone(); person.setCar((Car) person.getCar().clone()); return person; }
转载:【Java】实现对象克隆的三种方式(Cloneable接口、Java自身序列化、FastJson序列化)_克隆方式创建对象-CSDN博客
代码示例
1.浅拷贝
@Data
public class Student implements Cloneable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object clone = super.clone();
return clone;
}
}
@Data
public class Teacher implements Cloneable {
private String name;
private Student student;
public Teacher(String name, Student student) {
this.name = name;
this.student = student;
}
@Override// 浅拷贝
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Student student = new Student("张三",15);
Teacher teacher = new Teacher("张老师",student);
// 浅拷贝
Teacher teacherLi = (Teacher) teacher.clone();
System.out.println("student更换前=========>" );
System.out.println("teacher" + teacher);// "张老师","张三",15
System.out.println("teacherLi" + teacherLi);// "张老师","张三",15
student.setName("李四");
student.setAge(16);
System.out.println();
System.out.println("student更换后=========>" );
System.out.println("teacher" + teacher);// "张老师","李四",16
System.out.println("teacherLi" + teacherLi);// "张老师","李四",16
}
2.深拷贝
@Data
public class Student implements Cloneable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object clone = super.clone();
return clone;
}
}
@Data
public class Teacher implements Cloneable {
private String name;
private Student student;
public Teacher(String name, Student student) {
this.name = name;
this.student = student;
}
@Override// 深拷贝
protected Object clone() throws CloneNotSupportedException {
Teacher teacher= (Teacher) super.clone();
teacher.setStudent((Student) teacher.getStudent().clone());
return teacher;
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Student studentxx = new Student("张三",15);
Teacher teacher = new Teacher("张老师",studentxx);
// 深拷贝
Teacher teacherShi = (Teacher) teacher.clone();
System.out.println("student更换前=========>" );
System.out.println("teacher" + teacher);// "张老师","张三",15
System.out.println("teacherShi" + teacherShi);// "张老师","张三",15
studentxx.setName("李四");//studentxx对象本身设置值,和teacherShi没有关系
studentxx.setAge(16);
System.out.println();
System.out.println("student更换后=========>" );
System.out.println("teacher" + teacher);// "张老师","李四",16
System.out.println("teacherShi" + teacherShi);// "张老师","张三",15
}
17、throw 和 throws 区别
1、throw代表动作,表示抛出一个异常动作; throws代表一种状态,代表方法可能有异常抛出。
2、throw用在方法实现中,而throws用在方法声明中。
3、throw只能用于抛出一种异常,而throws可以抛出多个异常。
修饰符 返回值类型 方法名(参数列表) [throws 异常的类型] {
if (判断条件) {
throw new 异常对象("异常的原因");
}
}
18、final、finally、finalize 区别
final修饰的类表示最终类,不能被继承;修饰的变量表示常量;修饰的方法表示最终方法,不能被重写。
finally常用在try--catch--finally--的抛出异常,表示这个方法是否有异常都会执行finally的方法;如果catch里面有输出A和return的返回语句B,还有finally的方法C,那么执行的顺序是A-->C-->B,
finalize方法用于堆对象回收,释放空间的时候调用,可以描述为垃圾回收。
19、常见的异常类
NullPointerException:空指针异常;
IndexOutOfBoundsException:索引越界异常
ClassCastException:类型转换异常
NumberFormatException:数字转换异常
IllegalArgumentException 参数不合法异常
24、hashcode是什么
hascode是散列码值,可以大幅提高集合的查找速度,hascode将需要查找的对象计算成一个哈希码,通过算法将哈希码分到对应的存储分区上,这样可以大大提高查找速度。
25、java 中操作字符串
String:不可变字符串,定义的值会直接存储到字符串常量池当中,如果不存在的话;
StringBuilder:可变字符传,常用语追加字符串,线程不安全,单线程,效率比较高。
StringBuffer:可变字符串,效率不如StringBuilder快,线程安全,多线程。
26、java 中都有哪些引用类型
(1)强引用 例如Object,不会被gc回收,如果要回收可以将object重置为null。
(2)软引用(SoftReference),内存不足的时候会被回收,回收后内存还是不足,会内存溢出。
byte[] buff = new byte[1024 * 1024];
SoftReference<byte[]> sr = new SoftReference<>(buff);
(3)弱引用(WeakReference),gc会回收。
(4)虚引用(PhantomReference)
(5)引用队列(ReferenceQueue)
27、为什么不允许从静态方法中访问非静态变量
因为静态变量属于类的本身,在类加载的手就分配内存空间,可以直接通过类名来访问;
但是非静态变量属于类的对象,只有在new对象的时候,通过实例去访问;
28、Java Bean的命名规范
public class YdlhUtil {}首先是一个公共类,设置的实体类需要通过set和get方法来获取,默认存在空参构造函数可以使用。
29、Java Bean 属性命名规范问题分析
驼峰式命名 busName
方法的命名 建议为 getName()
31、什么情况下会更倾向于使用抽象类而不是接口
抽象类倾向于描述公共的内容,写成抽象方法,通过子类继承实现方法的重写;
接口是倾向于总结的工具,更侧重于某个功能的使用。
32、Java 容器都有哪些?
集合:collection、set、list、map
33、Collection 和 Collections 区别
Collection是一个结合类,包含的子类有set和list,可以根据使用的需求不同分别使用。
Collections是一个工具类,包含的静态方法可以直接通过.的形式使用。
34、list与Set区别
①List,Set都是继承自Collection接口
② List特点:有序可重复 ,Set特点:无序,不可重复(哈希值)
Set:查询慢,插入删除快。 (注意:元素虽然无放入顺序,但元素在 Set 中的位置是由该元素的 HashCode 决定的,其位置是固定的,加入 Set 的 Object 必须定义 equals()方法),Set 只能用迭代,因为它是无序的。
List:查询快,插入删除慢(List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。)
39、ArrayList和LinkedList查询之间的区别?
- LinkedList 是基于链表实现的,适合插入。
- ArrayList是基于数组实现的,适合查询。
40、HashMap 和 Hashtable 有什么区别?
- HashMap是线程不安全的,HashTable是线程安全的;
- HashMap中允许键和值为null,HashTable不允许;
- HashMap的默认容器是16,为2倍扩容,HashTable默认是11,为2倍+1扩容;
- HashMap数据+链表+红黑树的存储形式,HashTable数据存储结构都是数组+链表。
43、如何实现数组和 List 之间的转换?
Arrarys.asList(数组包装类)’方法,将数组转化成List
阻塞和非阻塞 同步和异步
同步/异步,阻塞/非阻塞概念深度解析_同步异步阻塞非阻塞-CSDN博客
44、在 Queue 中 poll()和 remove()有什么区别?
Queue是spring原生队列,继承Collection,这两个方法都代表删除删除第一个元素,remove删除失败抛出异常,poll删除失败返回false
45、哪些集合类是线程安全的
Vector:就比Arraylist多了个同步化机制(线程安全)。
Stack:栈,也是线程安全的,继承于Vector。
Hashtable:就比Hashmap多了个线程安全。
46、迭代器 Iterator 是什么?
java.util.Collection 接口的 iterator() 方法返回一个 Iterator 对象
next() 方法获得集合中的下一个元素
hasNext() 检查集合中是否还有元素
remove() 方法将迭代器新返回的元素删除
49、怎么确保一个集合不能被修改?
Collections.unmodifiableXXX(XXX)
50、队列和栈是什么?有什么区别?
(1)队列先进先出,栈先进后出。
(2)遍历数据速度不同。
栈只能从头部取数据 需遍历整个栈后才能取出来,而且在遍历数据的时候还得为数据开辟临时空间,保持数据在遍历前的一致性;
队列则不同,基于地址指针进行遍历,而且可以从头或尾部开始遍历,但不能同时遍历,无需开辟临时空间,因为在遍历的过程中不影像数据结构,速度要快的多。