主题
java 面试题
写在前面:理解后尽量把问题简单化,用最简单的语言概括核心问题,不要大段书面化的阐述,一是啰嗦,二是记起来困难 三是你给面试官那么讲,估计效果也不好
1.什么是 JDK?什么是 JRE? - 不是重点,了解一下即可
1、JDK:java development kit:java 开发包,是开发人员所需要安装的环境。
2、.JRE:java runtime environment:java 运行环境,java 程序运行所需要安装的环境。

2.java 语言有哪些特点?- 不是重点,了解一下即可,但是一定要知道两个个特点:面向对象、可移植(跨平台,而且要明白跨平台的原理),其他的看一眼就行
Java 语言共有十大特点,分别为:简单性、面向对象、分布性、编译和解释性、稳健性、安全性**、可移植性**、高性能、多线索性(多线程吧)、动态性。
1、简单性:Java 语言继承了 C++ 语言的优点,去掉了 C++ 中学习起来比较难的多继承、指针等概念,所以 Java 语言学习起来更简单,使用起来也更方便。
2、面向对象:Java 是一种面向对象的编程语言。要理解什么是面向对象(高频面试题)
3、分布性:Java 设计成支持在网络上应用,它是分布式语言。所以只要用 Java 编写了一个程序,就可以到处应用。可以节省大量人力物力。
4、编译和解释性:Java 编译程序生成字节码,而不是通常的机器码,这使得 Java 开发程序比用其他语言开发程序快很多。
5、稳健性:Java 刚开始被设计出来就是为了写高可靠和稳健的软件的。所以用 Java 写可靠的软件很容易。目前许多第三方交易系统、银行平台的前台和后台电子交易系统等都会用 Java 语言开发。
6、安全性:Java 的存储分配模型是它防御恶意代码的主要方法之一。所以很多大型企业级项目开发都会选择用 Java 开发。
7、可移植性:Java 并不依赖平台,用 Java 编写的程序可以运用到任何操作系统上**。-原理是什么**
java 编写的文件是.java 文件,.java 文件编译之后变为.class 文件,.class 文件在 jvm 里运行(任何操作系统都有对应的 jvm),所以 java 是一处编译到处执行,并不依赖于平台。
8、高性能:Java 是一种先编译后解释的语言,所以它不如全编译性语言快。但 Java 设计者制作了“及时”编译程序,这样就可以实现全编译了。
9、多线索性(多线程吧):Java 是多线索语言,它可以同时执行多个程序,能处理不同任务。
10、动态性:Java 语言设计成适应于变化的环境,它是一个动态的语言。
3.java 的数据结构有哪些
1、数组
2、链表
3、栈
4、队列
5、图
6、树
7、跳表
8、哈希表
4、java 中八大基本数据类型有哪些?-以及他们对应的八个包装类,还有包装类与基本数据类型的区别
整形:int--Integer、short--Short、long--Long、byte--Byte
浮点类型:float--Float、double--Double
字符类型:char--Character
布尔类型:boolean--Boolean
包装类:是一个对象,拥有属性和方法,基本数据类型不是;
包装类型是引用传递;基本数据类型是值传递;
存储位置不同,基本数据类型直接将值保存在值栈中,而包装类型是把对象放在堆中,然后通过对象的引用来调用他们
初始值不同,eg: int 的初始值为 0 、 boolean 的初始值为 false 而包装类型的初始值为 null
5.一个 java 类中包含哪些内容? - 这个问题让我有点懵逼,不过总结的挺好
属性、方法、内部类、构造方法、代码块
6.那针对浮点类数据运算出现的误差的问题,你怎么解决?
使用 Bigdecimal 类进行浮点型数据的运算。
7.面向对象的特征有哪些方面?-这题是重点,抽象不是面向对象的特征,可以去看看书
1、继承:就是父子关系;子类可以继承父类的方法和属性。
2、封装:封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。比如将一个实体的属性写成一个类封装起来,后期只需要调用这个类,而不需要去修改这个类属性和方法
3、多态:必须是在有继承的前提下,需要重写父类方法,父类引用指向子类对象,
如 List<Integer> list = new ArrayList<Integer>();
说下个人对知识点的理解:
上学的时候,都是为了考试,所以答案只要背下来,别人理解不理解都无所谓,因为判卷老师一看你是书上背的标准那就对满分,但是面试、上班不一样:你知道的东西是为了给别人讲明白,而且自己会用,所以你讲的特别书面化官方,对方不一定能听明白(所以他就无法确认的判断你会不会),个人观点啊,说的不对多包涵 喷我也可以。
8.访问修饰符 public、private、protected 以及不写(默认)时的区别?
| 修饰符 | 当前类 | 同包 | 子类 | 其他包 |
|---|---|---|---|---|
| public | 能 | 能 | 能 | 能 |
| protected | 能 | 能 | 能 | 不能 |
| default | 能 | 能 | 不能 | 不能 |
| private | 能 | 不能 | 不能 | 不能 |
类成员不写访问修饰时默认为 default。默认对同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对于子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。java 中,外部类的修饰符只能是 public 或默认,类的成员(包括内部类)的修饰符可以是以上四种。
9.String 是最基本的数据类型吗?
不是基本数据类型,除了八大基本数据类型,剩下的都是引用类型;java5 以后引入的枚举类型也算是一种比较特殊的引用类型。
10.重写和重载的区别?
1、访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private),子类的访问权限要大于父类
2、重写方法一定不能抛出新得检查异常或者比被重写方法申明更加宽泛的检查型异常。子类抛出的异常不能比父类大
总结一句话:父子类具有相同的方法,子类用@Override 注解表示重写。
重载:总结一句话:方法名相同,参数类型不同或顺序不同或返回值不同就是重载,这样背起来理解起来是不是简单的多。
11.equals 与==的区别?
总结:所有比较是否相等时,都是用 equals 并且在对常量相比较时,把常量写在前面,是因为使用 object 的 equals object 可能为 null 则空指针。
总结:==比较的是地址值,通常用于基本数据类型比较,equals 比较的是值。通常用于引用数据类型的比较,Object 下的 equals 方法默认比较的也是地址值,所以我们通常会重写 equals 方法。
bash
public boolean equals(Object obj) {
return (this == obj);
}12.java 常用的包有哪些?
Java.lang、java.io、java.util、java.sql、java.awt、java.net、java.math
13.Object 类常用的方法有哪些?
1.clone() 方法:实现对象的浅复制**(深拷贝与浅拷贝的区别)**
2.getClass() 方法;返回的是实体对象对应的 Class 对象
3.toString() 方法**:直接使用输出语句输出对象名的时候,其实通过改对象调用了其2si}toString()****CEHOLDERmsj63xuponsy8m7f}**CEHOLDERmsj631ohgfhr96bg},重写 equals 方法一般都要重写 hashcode 方法。
7.wait 方法:线程等待。
8.notify 方法:唤醒等待某个的线程。
9.notifyAll() 方法:唤醒所有等待的线程。
14.java 中有没有指针?
有指针,但是隐藏了,开发人员无法直接操作指针,由 jvm 来操作指针 - 这题我不了解
15.java 中成员变量,局部变量,静态变量的辨析

成员变量生命周期:成员变量随着对象的建立而建立,随着对象的消失而消失
**局部变量生命周期:**局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放
**静态变量声明周期:**与类的生命周期一致
16.final、finally、finalize 的区别?
1.final 是一个关键字
(1)final 类不能被继承,没有子类,final 类中的方法默认是 final 的。
(2)final 方法不能被子类的方法覆盖,但是可以被继承。
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为 final 方法。 使用 final 方法的原因有二:
1.把方法锁定,防止任何继承类修改它的意义和实现。
2.高效。编译器在遇到调用 final 方法时候会转入内嵌机制,大大提高执行效。这个让我豁然开朗,但是我不明白什么是内嵌机制
(3)final 的成员变量表示常量,只能被赋值一次,复制**(值)后地址值不再改变。(我觉得应该是地址值不在改变,而非值)**
bash
final TechUser user = new TechUser();
user.setPassword("aaa");
user.setUserName("bbbb");
user.setPassword("ddddd");
user.setUserName("gggggg");
-- 值是依然可以改变的1.用 final 修饰的成员变量表示常量,值一旦给定就无法改变!
2.final 修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
final 变量定义的时候,可以先声明,而不给初值,这中变量也称为 final 空白,无论什么情况,编译器都确保空白 final 在使用之前必须被初始化。-- 这句话说得是啥?????????
(4)final 不能用于修饰构造方法。- 可以解释下为什么吗
2.finally 是关键字,在异常处理中,try 子句中执行需要运行的内容,catch 子句用于捕获异常,finally 子句表示不管是否发生异常,都会执行。finally 可有可无。但是 try...catch 必须成对出现。(并不是必须成对出现的,如下图)

3.finalize() 方法名 (**是Object 类的HTML_PLACEHOLDERmsj63xup2hc1rzly}**个对象进行调用。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的子类覆盖 finalize() 方法以整理系统资源或者执行其他清理操作。 -- 我没明白这段话在讲什么
17.String、StringBuffer、StringBuilder 的区别是什么?
1.String 类被 final 修饰,所以 String 类型的字符串是常量,一旦创建不能被改变;StringBuilder 和 StringBuffer 是字符串变量,只能通过构造函数来建立对象,StringBuilder 和 StringBuffer 都是可以改变的;
2.StringBuilder 是线程不安全的,适用于单线程下;StringBuffer 通过synchronized 实现线程安全的,适用于多线程下。
应用场景:
- 在字符串内容不经常发生变化的业务场景优先使用 String 类。例如:常量声明、少量的字符串拼接操作等。如果有大量的字符串内容拼接,避免使用 String 与 String 之间的“+”操作,因为这 样会产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)。
- 在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在 多线程 环境下,建议使用 StringBufer,例如 XML 解析、HTTP 参数解析与封装。
- 在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在 单线程 环境下,建议使用 StringBuilder,例如 SQL 语句拼装、JSON 封装等。
18.java 中的继承是单继承还是多继承?
java 中的既有单继承,又有多继承。对于 java 类来说只能有一个父类,对于接口来说可以同时继承多个接口。
19.super 与 this 表示什么?
super 表示当前类的父类对象;this 表示当前类的对象。
20.普通类与抽象类有什么区别?
普通类不能包含抽象方法,普通类可以直接实例化。
抽象类可以包含抽象方法;抽象类不能直接实例化,抽象类用 abstract 修饰,抽象方法必须在抽象类中,抽象类可以没有抽象方法
21.抽象类与接口的区别?
抽象类:
抽象类用 abstract 修饰,抽象方法必须在抽象类中,抽象类可以没有抽象方法
抽象类不能被实例化
接口:
接口用 interface 修饰
接口中的变量都是常量,默认被 public static final 修饰,方法都是抽象方法
接口不能被实例化
接口之间的继承是多继承,接口被子类实现,需要重写接口中的所有抽象方法
以上是写法上的区别,思想设计上的区别,个人认为是:抽象的分层,接口是用于定义行为和规范,更抽象;抽象类可以有实现也可以有抽象,抽象类还一个作用是实现代码的复用(这个要求比较高了,初级程序员答得出来答不出来影响不大) 方法**
在 HashSet 中判断对象是否存在集合中
1.调用 obj.hashCode(),得到对应的 hashcode 值。
2.如果集合中没有存储这个 hashcode 对应的对象,则直接添加。如果集合中已经存储了这个 hashcode 对应的对象,则调用 equals 判断是否对象相同。
为了保证 equals 方法返回的结果和 hashCode 方法返回的结果一样,所以重写 equals 方法的同时也要重写 hashCode 方法。
23.java 的四种引用 - 这个研究的不深,个人觉得了解一下就好,强引用必须知道。
强引用:强引用是平时使用最多的引用,强引用在程序中内存不足(OOM)的时候也不会被回收,会报错,使用方式:
java
String str = new String("str");软引用:软引用在程序内存不足时,会被收回,使用方式:
java
//注意:wrf这个引用也是强引用,它是指向SoftReference这个对象的。
//这里的软引用指的是指向 new String("str")的引用,也就是SoftReference类中的T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));可用场景:创建缓存的时候,创建的对象放进缓存中,当内存不足时,jvm 就会回收早先创建的对象。
弱引用:弱引用就是只要 jvm 垃圾回收器发现了它,就会将他回收,使用方式:
java
WeakReference<String> wrf = new WeakReference<String>(str);可用场景:java 源码中的 java.utils.WeakHashMap 中的 key 就是使用弱引用,一旦我不需要某个引用,JVM 会自动帮我处理它,这样我就不需要做其他操作。
虚引用:虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入 ReferenceQueue 中。其他引用是被 jvm 回收之后才被传入 ReferenceQueue 中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。虚引用创建的时候,必须带有 ReferenceQueue,使用方式:
java
PhantomReference<String>prf=newPhantomReference<String>(new
String("str"),newReferenceQueue<>());可用场景: 对象销毁前的一些操作,比如说资源释放等。** Object.finalize() 虽然也可以做这类动作,但是这个方式即不安全又低效
上诉所说的几类引用,都是指对象本身的引用,而不是指 Reference 的四个子类的引用 ( SoftReference 等)。
24.java 创建对象有几种方式?
1、new 创建新对象
2、通过反射机制
3、采用 clone 机制
4、通过反序列化机制
25.有没有可能两个不相等的对象有相同的 hashcode? - 这个题上面讲过啦,整理一下
有可能.在产生 hash 冲突时,两个不相等的对象就会有相同的 hashcode 值.当 hash 冲突产生时,一般有以
下几种方式来处理:
- 拉链法: 每个哈希表节点都有一个 next 指针,多个哈希表节点可以用 next 指针构成一个单向链表,被
分配到同一个索引上的多个节点可以用这个单向链表进行存储.
- 开放定址法: 一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找
到,并将记录存入
- 再哈希: 又叫双哈希法,有多个不同的 Hash 函数.当发生冲突时,使用第二个,第三个….等哈希函数计算
地址,直到无冲突.
26.深拷贝和浅拷贝的区别是什么?
深拷贝浅拷贝都是基于原有对象拷贝一个新的对象,区别在于对原有对象的成员变量的拷贝机制不同。
浅拷贝:将原对象的基本类型成员变量复制其值,引用类型变量复制其地址值,及原对象引用类型的变量与拷贝对象的引用类型变量实际指向的是一个对象。
深拷贝:将原对象的基本类型成员变量复制其值,引用类型变量复制其值并创建一个新对象,及原对象引用类型的变量与拷贝对象的引用类型变量实际指向的是两个对象。
27.JDBC 操作步骤 - 可以说的具体一点,参考下面我贴的代码
1、加载数据库驱动类
2、打开数据库链接
3、执行 sql 语句
4、处理返回结果
5、关闭资源
bash
public static void main(String[] args) {
//所有处理数据库相关的都是如下几步,都采用的jdbc技术
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/tech_shop?characterEncoding=utf-8","root", "root");
// ? 表示占位符
String sql = "select * from tech_user where user_id = ?";
//获取预处理 statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的 参数值
preparedStatement.setLong(1, 0);
//
//向数据库发出 sql 执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println("==========" + resultSet.getString("user_id"));
System.out.println("==========" + resultSet.getString("user_name"));
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement != null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}28.在使用 jdbc 的时候,如何防止出现 sql 注入的问题;怎么在 jdbc 内调用一个存储过程
使用 PreparedStatement 类,而不是使用 Statement 类。使用 CallableStatement。
为什么****PreparedStatement 为什么可以防止 sql 注入:
当我们使用 PreparedStatement 去写 sql 语句时,程序会对该条 sql 首先进行预编译,然后会将传入的字符串参数以字符串的形式去处理,即会在参数的两边自动加上单引号(’param’)这样就防止出现 sql 注入的问题。而 Statement 则是直接简单粗暴地通过人工的字符串拼接的方式去写 sql,那这样就很容易被 sql 注入。
29.是否了解连接池,使用连接池有什么好处?
数据库连接是非常消耗资源的,影响到程序的性能指标。连接池是用来分配、管理、释放数据库连接
的,可以使应用程序重复使用同一个数据库连接,而不是每次都创建一个新的数据库连接。通过释放空
闲时间较长的数据库连接避免数据库因为创建太多的连接而造成的连接遗漏问题,提高了程序性能。-- 这句话感觉解释的好模糊。
**连接池解决的核心问题就是资源管理问题,在并发环境下,系统不能确定在任意时刻中,有多少任务需要执行,就有多少资源投入。为解决资源分配问题,连接池采用了“池化思想”,是为了最大化收益,最小风险,而将资源统一在一起管理的一种思想。常见的有:****实例池:循环使用对象,减少资源在初始化和释放时的昂贵损坏。**比较多
Dbcp,c3p0 等,用的最多还是 c3p0,因为 c3p0 比 dbcp 更加稳定,安全;通过配置文件的形式来维护数
据库信息,而不是通过硬编码。当连接的数据库信息发生改变时,不需要再更改程序代码就实现了数据
库信息的更新。
31.a.hashCode() 有什么用?与 a.equals(b) 有什么关系? 还是 hashcode 与 equals 的问题
hashCode() 方法是相应对象整型的 hash 值。它常用于基于 hash 的集合类,如 Hashtable、
HashMap、LinkedHashMap 等等。-- 这句话删了吧
它与 equals() 方法关系特别紧密。根据 Java 规范,两个使用 equal() 方法来判断相等的对象,必须具有相同的 hashcode。
32.break 和 continue 的区别 这个没问题
在循环体内,break 语句和 continue 语句的区别在于: 使用 break 语句是跳出当前循环,并执行当前循环之后的语句;而 continue 语句是终止当前循环,并继续执行下一次循环。
33.两个对象值相同(x.equals(y)==true),但有不同的 hashcode,这句话对不对?还是 hashcode 与 equals 的问题
不对,如果两个对象 x 和 y 满足 x.equals(y) == true,它们的哈希码(hash code)应当相同。Java 对
于 eqauls 方法和 hashCode 方法是这样规定的:
(1) 如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同;
(2) 如果两个对象的 hashCode 相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你
违背了上述原则就会发现在使用容器时,相同的对象可以出现在 Set 集合中,同时增加新元素的效率会
大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。
34.是否可以继承 String 类?
String 类是 final 类,不可以被继承,继承 String 本身就是一个错误的行为。
35.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被 synchronized 修饰?
都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本
地代码(如 C 代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized 和方法的实
现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。-- 这叫解释的原因吗?????????
**关于 abstract 跟****synchronized 能不能同时修饰一个方法,确实是没见过这么问的,****ML_PLACEHOLDERmsj63xuov91ttao4}*****abstract 方法必须在抽象类中,不能被实例化,所以这是互相矛盾的。**hl86ttkab}
LinkedList:
底层数据结构是链表,查询慢,增删快。使用场景 读少,写多
线程不安全,效率高。
底层存储原理:数组与链表的区别:
1.ArrayList 是基于数组实现的,所以查找速度快:

增加删除慢的原因:
1.插入或删除元素:

2.LinkedList 底层数据结构是链表
优点:删除和添加元素的效率比较高
缺点:数据结构复杂 分为单向链表和双向链表(LinkedList 底层是双向链表)
bash
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}删除和添加元素的效率比较高的原因:
以单向链表为例;

ArrayList 数组和 LinkedList 链表:
数组查询快的原因:数组简单易用,使用的是连续的内存空间,可以借助 CPU 的缓存机制,预读数组中的数据,所以访问的下效率更高。而链表在内存中并不是连续存储的,所以对 CPU 缓存不友好,没办法预读。
对于数组来说,存储空间是连续的,所以在加载某个下标的时候可以把以后的几个下标元素也加载到 CPU 缓存这样执行速度会快于存储空间不连续的链表存储。
CPU 在从内存读取数据的时候,会先把读取到的数据加载到 CPU 的缓存中。而 CPU 每次从内存读取数据并不是只读取那个特定要访问的地址,而是读取一个数据块,并保存到 CPU 缓存中,然后下次访问内存数据的时候就会先从 CPU 缓存开始查找,如果找到就不需要再从内存中取。这样就实现了比内存访问速度更快的机制,也就是 CPU 缓存存在的意义 : 为了弥补内存访问速度过慢与 CPU 执行速度快之间的差异而引入。
37.HashMap 和 HashTable 的区别(掌握 1 3 4 点就行,都背下来太困难)
1、两者父类不同:HashMap 是继承自 AbstractMap 类,而 Hashtable 是继承自 Dictionary 类。不过它们都实现了 map、Cloneable(可复制)、Serializable(可序列化)这三个接口。
2、对外提供的接口不同:Hashtable 比 HashMap 多提供了 elments() 和 contains() 两个方法。
elments() 方法继承自 Hashtable 的父类 Dictionnary。elements() 方法用于返回此 Hashtable 中的
value 的枚举。
contains() 方法判断该 Hashtable 是否包含传入的 value。它的作用与 containsValue() 一致。事实上,
contansValue() 就只是调用了一下 contains() 方法。
3、对 null 的支持不同
Hashtable:key 和 value 都不能为 null。
HashMap:key 可以为 null,但是这样的 key 只能有一个,因为必须保证 key 的唯一性;可以有多个 key
值对应的 value 为 null。
4、安全性不同
HashMap 是线程不安全的,在多线程并发的环境下,可能会产生死锁等问题(额 hashmap 的增删改都没有锁,为啥会出现死锁,哪来的锁),因此需要开发人员自己,处理多线程的安全问题。
不是会出现死锁,是在 jdk1.7 版本的 hashmap 会出现死循环问题(链表成环),因为 jdk1.7 采用的头插法,jdk1.8 采用的是尾插法。(了解一下就行,等下次再换工作的时候可以研究一下)
Hashtable 是线程安全的,它的每个方法上都有 synchronized 关键字,因此可直接用于多线程中。
虽然 HashMap 是线程不安全的,但是它的效率远远高于 Hashtable,这样设计是合理的,因为大部分的
使用场景都是单线程。当需要多线程操作的时候可以使用线程安全的 ConcurrentHashMap。
ConcurrentHashMap 虽然也是线程安全的,但是它的效率比 Hashtable 要高好多倍。因为 ConcurrentHashMap 使用了分段锁,并不对整个数据进行锁定。
38.Collection 包结构,与 Collections 的区别
Collection 是集合类上级接口,子接口有 Set、List、LinkedList、ArrayList、Vector、Stack、Set;
Collections 是集合类的一个帮助类, 它包含有各种有关集合操作的静态多态方法,用于实现对各种集
合的搜索、排序、线程安全化等操作。此类不能实例化,就像一个工具类,服务于 Java 的 Collection 框
架。
39.说说 List、set、map 三者的区别
List: List 接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象
List:存取有序,元素可重复,子类 ArrayList LinkedList Vector
Set(注重独一无二的性质): 不允许重复的集合。不会有多个元素引用相同的对象。
Set:存取无序,元素不可重复,子类 TreeSet(默认自然排序) HashSet(底层就是 HashMap 的 key)
Map: 使用键值对存储。Map 会维护与 Key 有关联的值。两个 Key 可以引用相同的对象,但 Key 不能重复。
map 就是用来存储键值对的 特点 key 不能重复 - 记住这句话就行啦
40.Array 与 ArrayList 有什么不一样?
Array 与 ArrayList 都是用来存储数据的集合。ArrayList 底层是使用数组实现的,但是 arrayList 对数组进
行了封装和功能扩展,拥有许多原生数组没有的一些功能。我们可以理解成 ArrayList 是 Array 的一个升
级版。
41.集合类存放于 java.util 包中,主要有几种接口
主要包含 set(集)、 list(列表包含 Queue)和 map(映射)。
- Collection: Collection 是集合 List、 Set、 Queue 的最基本的接口。
- Iterator:迭代器,可以通过迭代器遍历集合中的数据
- Map:是映射表的基础接口

42.Vector
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector 相对 ArrayList 查询慢 (线程安全的)
Vector 相对 LinkedList 增删慢 (数组结构)
Vector 与 ArrayList 一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一 个线
程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此, 访问它
比访问 ArrayList 慢 。
Vector是线程安全的,vector中大部分方法增加了Sychronized关键字修饰;
Vector 实现了一个可以自动增长的对象数组,类似于动态数组,能够调整自身的大小,能够根据索引进行查询;
Vector 实现了**RnadomAccess(单词拼错了)**接口,因此能够队数据进行随机访问。
43.什么是 TreeSet(二叉树)
- TreeSet() 是使用二叉树的原理对新 add() 的对象按照指定的顺序排序(升序、降序),每增 加一个
对象都会进行排序,将对象插入的二叉树指定的位置。
- Integer 和 String 对象都可以进行默认的 TreeSet 排序(是按照自然顺序排序,不是默认的 TreeSet 排序,自然排序是指数字按 1 2 3 4....排序,字母按 a b c d......排序),而自定义类的对象是不可以的, 自 己定
义的类必须实现 Comparable 接口,并且覆写相应的 compareTo() 函数,才可以正常使 用。
- 在覆写 compare() 函数时,要返回相应的值才能使 TreeSet 按照一定的规则来排序
4. 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整 数、零
或正整数 (请问这句话理解吗?)
44.说说 LinkedHashSet(HashSet+LinkedHashMap)
对于 LinkedHashSet 而言,它继承与 HashSet、又基于 LinkedHashMap 来实现的。 LinkedHashSet
底层使用 LinkedHashMap 来保存所有元素,它继承与 HashSet,其所有的方法 操作上又与 HashSet
相同,因此 LinkedHashSet 的实现上非常简单,只提供了四个构造方法,并 通过传递一个标识参数,
调用父类的构造器,底层构造一个 LinkedHashMap 来实现,在相关操 作上与父类 HashSet 的操作相
同,直接调用父类 HashSet 的方法即可。
并没有说出****LinkedHashSet 有啥特点?????
45.HashMap
HashMap 根据键的 hashCode 值来定位索引,并不是存储数据 存储数据,大多数情况下可以直接定位到它的值,因而具有很快 的访问速度,但遍历顺序却是不确定的。 HashMap 最多只允许一条记录的键为 null,允许多条记 录的值为 null。 HashMap 非线程安全,即任一时刻可以有多个线程同时写 HashMap,可能会导致数据的不一的 synchronizedMap 方法使 HashMap 具有线程安全的能力,或者使用 ConcurrentHashMap。 我们用下面这张图来介绍 HashMap 的结构。
key - value
线程不安全
hashmap 底层数据结构是哈希表 数组 + 链表
java7 hashmap 结构:

大方向上, HashMap 里面是一个数组,然后数组中每个元素是一个单向链表。上图中,每个绿色 的实
体是嵌套类 Entry 的实例, Entry 包含四个属性: key, value, hash 值和用于单向链表的 next。
- capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。
- loadFactor:负载因子,默认为 0.75。
- threshold:扩容的阈值,等于 capacity * loadFactor
默认容量是 16
Java8 对 HashMap 进行了一些修改, 最大的不同就是利用了红黑树,所以其由 数组 + 链表 + 红黑 树 组
成。 根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的
具体下标,但是之后的话, 需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决 于链
表的长度,为 O(n)。为了降低这部分的开销,在 Java8 中, 当链表中的元素超过了 8 个以后, 会将链
表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。
java8HashMap 结构:

46.HashTable(线程安全)
Hashtable 是遗留类,很多映射的常用功能与 HashMap 类似,不同的是它承自 Dictionary 类, 并且是线程安全的,任一时间只有一个线程能写 Hashtable,并发性不如 ConcurrentHashMap, 因为 ConcurrentHashMap 引入了分段锁。 Hashtable 不建议在新代码中使用,不需要线程安全 的场合可以用 HashMap 替换,需要线程安全的场合可以用 ConcurrentHashMap 替换(理解分段锁原理吗?)
47.TreeMap(可排序)
TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序, 也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。 如果使用排序的映射,建议使用 TreeMap。 在使用 TreeMap 时, key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的 Comparator,否则会在运行时抛出 java.lang.ClassCastException 类型的异常。
48.泛型类
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
java
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}没有说到关键点上,泛型的作用是在编译期对数据类型进行检查约定(记住是编译期哦,运行时会进行泛型擦除)。理解到这一点就行啦,上面的不用记,学习东西首先要明白他解决了什么问题,为什么会有他,明白了之后再去学如何使用。
49.注解是什么 - 理解注解的作用,会用就可以啦,这么多东西背下来也挺困难的。
注解的含义:注解相当于一个标签。
注解是用来修饰类、方法、变量、参数、包;相当于注解是给类、方法、成员变量打了个标签。
注解分为三类:
1.java 及框架自带的注解; 如:@Overrride、@Controller
2.自定义注解(自己定义编写的注解)
java
package com.foxlink.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface DoneOperate {
String param() default "";
}3.元注解(注解的注解)如:@Target、@Retention
@Target 表示注解作用在方法上、还是在类上、变量上。
@Retention 表示作用在哪个时间段(类有生命周期、编译期、运行期)
50.四种标准元注解是哪四种?理解注解的作用,会用就可以啦,这么多东西背下来也挺困难的。
元注解的作用是负责注解其他注解。 Java5.0 定义了 4 个标准的 meta-annotation 类型,它们被用来提供对其它 annotation 类型作说明。
@Target 修饰的对象范围
@Target 说明了 Annotation 所修饰的对象范围: Annotation 可被用于 packages、types(类、接口、枚举、Annotation 类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch 参数)。在 Annotation 类型的声明中使用了 target 可更加明晰其修饰的目标
@Retention 定义 被保留的时间长短
Retention 定义了该 Annotation 被保留的时间长短:表示需要在什么级别保存注解信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效),取值(RetentionPoicy)由:
- SOURCE: 在源文件中有效(即源文件保留)
- CLASS: 在 class 文件中有效(即 class 保留)
- RUNTIME: 在运行时有效(即运行时保留)
@Documented 描述-javadoc
@ Documented 用于描述其它类型的 annotation 应该被作为被标注的程序成员的公共 API,因此可以被例如 javadoc 此类的工具文档化。
@Inherited 阐述了某个被标注的类型是被继承的
@Inherited 元注解是一个标记注解,@Inherited 阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited 修饰的 annotation 类型被用于一个 class,则这个 annotation 将被用于该 class 的子类。
补充问题:
java 的异常体系
for 循环 while 循环 do while 循环的区别
static 关键字的作用
冯诺依曼计算机体系
关于微服务与分布式
从概念理解,分布式服务架构强调的是服务化以及服务的分散化,微服务则更强调服务的专业化和精细分工;
从实践的角度来看,微服务架构通常是分布式服务架构,反之则未必成立。所以,选择微服务通常意味着需要解决分布式架构的各种难题。
微服务重在解耦合,使每个模块都独立。分布式重在资源共享与加快计算机计算速度。
总结:分布式在于分散压力;微服务在于分散能力。
框架
springcloud 跟 springboot 还有springcloudAlibaba
在18年以前,那时最流行分布式,微服务的概念并没有得到很广泛的应用,所以那时常用框架就是
ssm、dubbo、zookeeper,而微服务流行也正是得益于springboot、springcloud的诞生,springboot是对spring、springmvc的封装
让配置集成变得更简单化,所以18年后开始流行使用springboot,springcloud包含一套完整的微服务体系,但是他的基础是springboot,
springcloud微服务体系包含eureka、fegin、ribbon、config、gateway等等(也就是注册中心、远程调用、负载均衡、限流、网关、链路追踪、配置中心等等)
springcloud目前属于阿帕奇公司
springcloudAlibaba 是阿里巴巴根据springcloud开发出的一套微服务体系