一、基础部分
- JDK 和 JRE 的区别
- == 和 equals 的区别
- 基本类型和包装类对象使用 == 和 equals进行比较的结果?
- 什么是装箱?什么是拆箱?装箱和拆箱的执行过程?常见问题?
- hashCode()相同,equals() 也一定为 true吗?
- final 在 java 中的作用
- final finally finalize()区别
- finally语句块一定执行吗?
- final 与 static 的区别
- return 与 finally 的执行顺序对返回值的影响
- String对象中的replace和replaceAll的区别?
- Math.round(-1.5) 等于多少?
- String 属于基础的数据类型吗?
- java 中操作字符串都有哪些类?它们之间有什么区别?
- 如何将字符串反转?
- String 类的常用方法
- 普通类和抽象类有哪些区别?
- 抽象类必须要有抽象方法吗?
- 抽象类能使用 final 修饰吗?
- 接口和抽象类有什么区别?
- Java4种访问修饰符权限的区别?
- Java中的 << << >>> 是什么?
- javap 指令
- throw 和 throws 的区别?
- try-catch-finally 中哪个部分可以省略?
- 常见的异常类有哪些?
二、IO
- ava 中 IO 流有哪些?
- BIO、NIO、AIO 有什么区别?
- 什么是JAVA内部类?
- nio中的Files类常用方法
三、集合
- java 有哪些常用容器(集合)?
- Collection 和 Collections 有什么区别?
- List、Set、Map 之间的区别是什么?
- HashMap 和 Hashtable 有什么区别?
- 使用 HashMap 还是 TreeMap?
- HashMap 的实现原理
- HashSet 的实现原理
- ArrayList 和 LinkedList 的区别
- 如何实现数组和 List 之间的转换?
- ArrayList 和 Vector 的区别是什么?
- Array 和 ArrayList 有何区别?
- 在 Queue 中 add() 和 offer()有什么区别?
- Queue 中 remove() 和 poll()有什么区别?
- 在 Queue 中 element() 和 peek()有什么区别?
- 哪些集合类是线程安全的?
- 迭代器 Iterator 是什么?
- Iterator 怎么使用?有什么特点?
- Iterator 和 ListIterator 有什么区别
- 怎么确保一个集合不能被修改?
四、并发:
- 并行和并发有什么区别?
- 线程和进程的区别?
- 守护线程是什么?
- 创建线程有哪些方式?
- sleep() 和 wait() 有什么区别?
- Runnable 和 Callable 有什么区别?
- 线程有哪些状态?
- notify() 和 notifyAll() 有什么区别?
- JDK1.8 创建线程池有哪几种方式?
- 线程池有哪些状态?
- 线程池中 submit() 和 execute()方法有什么区别?
- java 程序中怎么保证多线程的运行安全?
- 多线程锁的升级原理是什么?
- 什么是死锁?
- 怎么防止死锁?
- ThreadLocal 是什么?有哪些使用场景?
- synchronized 底层实现原理?
- synchronized 和 volatile 的区别是什么?
- synchronized 和 Lock 有什么区别?
- synchronized 和 ReentrantLock 区别是什么?
- ReadWriteLock 如何使用?
- JDK 中 Atomic 开头的类实现原子性的原理是什么?
- 介绍一下 ForkJoinPool
- LongAdder 与AtomicLong有什么区别?
五、反射:
- 什么是反射?
- 动态代理是什么?应用场景?
- 怎么实现动态代理?
六、序列化:
- 什么是 java 序列化?什么情况下需要序列化?
七、克隆:
- 什么场景要对象克隆?
- 如何实现对象克隆?
- 深拷贝和浅拷贝区别是什么?
八、Web:
- jsp 和 servlet 有什么区别?
- jsp 有哪些内置对象?作用分别是什么?
- jsp 的 4 种作用域?
- session 和 cookie 有什么区别?
- session 的工作原理?
- 客户端禁止 cookie,session 还能用吗?
- http 响应码 301 和 302 代表的是什么?有什么区别?
- forward 和 redirect 的区别?
- tcp 和 udp 的区别?
- tcp 为什么要三次握手,两次不行吗?为什么?
- tcp 粘包是怎么产生的?
- OSI 的七层模型有哪些?
- get 和 post 请求有哪些区别?
- 如何实现跨域?
- JSONP 实现原理?
九、安全:
- 如何避免 sql 注入?
- 什么是 XSS 攻击,如何避免?
- 什么是 CSRF 攻击,如何避免?
十、设计模式:
- 常用的设计模式?
- 简单工厂和抽象工厂有什么区别?
十一、Spring框架:
- 为什么要使用 spring 框架?
- 什么是 aop?
- 什么是 ioc?
- spring 有哪些主要模块?
- spring 常用的注入方式有哪些?
- spring 中的 bean 是线程安全的吗?
- spring 支持几种 bean 的作用域?
- spring 自动装配 bean 有哪些方式?
- spring 事务实现方式有哪些?
- 介绍一下 spring mvc
- spring mvc 运行流程?
- spring mvc 有哪些组件?
- @RequestMapping 的作用是什么?
- @Autowired 的作用是什么?
- 什么是 spring boot?为什么要用?
- spring boot 核心配置文件是什么?
- spring boot 有哪些方式可以实现热部署?
十二、基础部门解析
1. JDK 和 JRE 的区别
JRE:Java Runtime Environment(java 运行时环境)。即 java 程序的运行时环境,包含了java虚拟机,java基础类库。
JDK:Java Development Kit(java 开发工具包)。即 java 语言编写的程序所需的开发工具包。
JDK包含了JRE,同时还包括 java 源码的编译器 javac、监控工具 jconsole、分析工具 jvisualvm 等。
2. == 和 equals 的区别是什么?
使用 == 比较
- Java 中的 8 种基本数据类型(byte,short,char,int,long,float,double,boolean)比较他们之间的值是否相等。
- 引用数据类型,比较的是他们在堆内存地址是否相等。每新 new 一个引用类型的对象,会重新分配堆内存空间,使用 == 比较返回 false。
3. 基本类型的包装类对象使用 == 和 equals() 进行比较
值不同
使用 == 和 equals() 比较都返回 false
值相同
使用 == 比较:
- 基本类型 - 基本类型、基本类型 - 包装对象返回 true
- 包装对象 - 包装对象返回 false
- 缓存中取的包装对象比较返回 true(原因是 JVM 缓存部分基本类型常用的包装类对象,如 Integer -128 ~ 127 是被缓存的)
使用 equals() 比较
- 包装对象-基本类型返回 true
- 包装对象-包装对象返回 true
4. Java 中的拆箱和装箱
什么是装箱?什么是拆箱?
- 装箱:基本类型转变为包装器类型的过程。
- 拆箱:包装器类型转变为基本类型的过程。
装箱和拆箱的执行过程?
- 装箱是通过调用包装器类的 valueOf 方法实现的
- 拆箱是通过调用包装器类的 xxxValue 方法实现的,xxx代表对应的基本数据类型。
- 如int装箱的时候自动调用Integer的valueOf(int)方法;Integer拆箱的时候自动调用Integer的intValue方法。
常见问题
- 整型的包装类 valueOf 方法返回对象时,在常用的取值范围内,会返回缓存对象。
- 浮点型的包装类 valueOf 方法返回新的对象。
- 布尔型的包装类 valueOf 方法 Boolean类的静态常量 TRUE | FALSE。
5. hashCode() 相同,equals() 也一定为 true吗?
首先,答案肯定是不一定。同时反过来 equals() 为true,hashCode() 也不一定相同。
- 类的 hashCode() 方法和 equals() 方法都可以重写,返回的值完全在于自己定义。
- hashCode() 返回该对象的哈希码值;equals() 返回两个对象是否相等。
关于 hashCode() 和 equals() 是方法是有一些 常规协定 :
- 两个对象用 equals() 比较返回true,那么两个对象的hashCode()方法必须返回相同的结果。
- 两个对象用 equals() 比较返回false,不要求hashCode()方法也一定返回不同的值,但是最好返回不同值,以提搞哈希表性能。
- 重写 equals() 方法,必须重写 hashCode() 方法,以保证 equals() 方法相等时两个对象 hashcode() 返回相同的值。
6. final 在 java 中的作用
final 语义是不可改变的。
- 被 final 修饰的类,不能够被继承。
- 被 final 修饰的成员变量必须要初始化,赋初值后不能再重新赋值(可以调用对象方法修改属性值)。对基本类型来说是其值不可变;对引用变量来说其引用不可变,即不能再指向其他的对象。
- 被 final 修饰的方法代表不能重写。
7. final finally finalize() 区别
- final 表示最终的、不可改变的。用于修饰类、方法和变量。
- finally 异常处理的一部分,它只能用在 try/catch 语句中,表示希望 finally 语句块中的代码最后一定被执行(存在一些情况导致 finally 语句块不会被执行,如 jvm 结束)
- finalize() 是在 java.lang.Object 里定义的,Object 的 finalize() 方法什么都不做,对象被回收时 finalize() 方法会被调用。特殊情况下,可重写 finalize() 方法,当对象被回收的时候释放一些资源,须调用 super.finalize() 。
8. finally 语句块一定执行吗?
答案是不一定。存在很多特殊情况导致finally语句块不执行。如:
- 直接返回未执行到 finally 语句块
- 抛出异常未执行到 finally 语句块
- 系统退出未执行到 finally 语句块
9. final 与 static 的区别
- 都可以修饰类、方法、成员变量。
- static 可以修饰类的代码块,final 不可以。
- static 不可以修饰方法内的局部变量,final 可以。
10. return 与 finally 的执行顺序对返回值的影响
对于 try 和 finally 至少一个语句块包含 return 语句的情况:
- finally 语句块会执行
- finally 没有 return,finally 对 return 变量的重新赋值修改无效
- try 和 finally 都包含return,return 值会以 finally 语句块 return 值为准
11. replace 和 replaceAll 的区别
replace方法:支持字符和字符串的替换。
public String replace(char oldChar, char newChar)
public String replace(CharSequence target, CharSequence replacement)
replaceAll方法:基于正则表达式的字符串替换。
public String replaceAll(String regex, String replacement)
12. Math.round(-1.5) 等于多少?
运行结果: -1
JDK 中的 java.lang.Math 类
- round() :返回四舍五入,负 .5 小数返回较大整数,如 -1.5 返回 -1。
- ceil() :返回小数所在两整数间的较大值,如 -1.5 返回 -1。
- tail() :返回小数所在两整数间的较小值,如 -1.5 返回 -2。
13. String 属于基础的数据类型吗?
不属于。
Java 中 8 种基础的数据类型:byte、short、char、int、long、float、double、boolean
但是 String 类型却是最常用到的引用类型。
14. java 中操作字符串都有哪些类?它们之间有什么区别?
Java 中,常用的对字符串操作的类有 String、StringBuffer、StringBuilder
- String : final 修饰,String 类的方法都是返回 new String。即对 String 对象的任何改变都不影响到原对象,对字符串的修改操作都会生成新的对象。
- StringBuffer : 对字符串的操作的方法都加了synchronized,保证线程安全。
- StringBuilder : 不保证线程安全,在方法体内需要进行字符串的修改操作,可以 new StringBuilder 对象,调用 StringBuilder 对象的 append()、replace()、delete() 等方法修改字符串。
15. 如何将字符串反转
- 使用 StringBuilder 或 StringBuffer 的 reverse 方法,本质都调用了它们的父类 AbstractStringBuilder 的 reverse 方法实现。(JDK1.8)
- 不考虑字符串中的字符是否是 Unicode 编码,自己实现。
String 类的常用方法
16. 普通类和抽象类有哪些区别?
- 抽象类不能被实例化
- 抽象类可以有抽象方法,抽象方法只需申明,无需实现
- 含有抽象方法的类必须申明为抽象类
- 抽象类的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类
- 抽象方法不能被声明为静态
- 抽象方法不能用 private 修饰
- 抽象方法不能用 final 修饰
17. 抽象类必须要有抽象方法吗?
不一定。如
public abstract class TestAbstractClass {
public static void notAbstractMethod() {
System.out.println("I am not a abstract method.");
}
}
18. 抽象类能使用 final 修饰吗?
不能,抽象类是被用于继承的,final修饰代表不可修改、不可继承的。
19. 接口和抽象类有什么区别?
- 抽象类可以有构造方法;接口中不能有构造方法。
- 抽象类中可以有普通成员变量;接口中没有普通成员变量。
- 抽象类中可以包含非抽象普通方法;接口中的所有方法必须都是抽象的。
- 抽象类中的抽象方法的访问权限可以是 public、protected 和 default;接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型。
- 抽象类中可以包含静态方法;JDK1.8 前接口中不能包含静态方法,JDK1.8 及以后可以包含已实现的静态方法。
public interface TestInterfaceStaticMethod {
static String getA() {
return "a";
}
}
- 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量可以是任意访问权限;接口中变量默认且只能是 public static final 类型。
- 一个类可以实现多个接口,用逗号隔开,但只能继承一个抽象类。
- 接口不可以实现接口,但可以继承接口,并且可以继承多个接口,用逗号隔开。
20. Java 中 4 种访问修饰符权限的区别?
Java 语言中有四种权限访问控制符,能够控制类中成员变量和方法的可见性。
public:
- 被 public 修饰的成员变量和方法可以在任何类中都能被访问到。
- 被 public 修饰的类,在一个 java 源文件中只能有一个类被声明为 public ,而且一旦有一个类为 public ,那这个 java 源文件的文件名就必须要和这个被 public 所修饰的类的类名相同,否则编译不能通过。
protected:
- 被 protected 修饰的成员会被位于同一 package 中的所有类访问到,也能被该类的所有子类继承下来。
friendly:
- 默认,缺省的。在成员的前面不写访问修饰符的时候,默认就是友好的。
- 同一package中的所有类都能访问。
- 被 friendly 所修饰的成员只能被该类所在同一个 package 中的子类所继承下来。
private:
- 私有的。只能在当前类中被访问到。
21. Java 中的 << >> >>> 什么意思?
-
<<
表示左移,不分正负数,低位补0 -
>>
表示右移,如果该数为正,则高位补0,若为负数,则高位补1 -
>>>
表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0
22. javap 工具是干什么的?
javap 是 Java class文件分解器,可以反编译,也可以查看 java 编译器生成的字节码等。
javap 命令参数
javap -help
用法: javap
其中, 可能的选项包括:
-help --help -? 输出此用法消息
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类
和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的
系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示静态最终常量
-classpath 指定查找用户类文件的位置
-bootclasspath 覆盖引导类文件的位置
23. throw 和 throws 的区别
throw:
- 表示方法内抛出某种异常对象
- 如果异常对象是非 RuntimeException 则需要在方法申明时加上该异常的抛出 即需要加上 throws 语句 或者 在方法体内 try catch 处理该异常,否则编译报错
- 执行到 throw 语句则后面的语句块不再执行
throws:
- 方法的定义上使用 throws 表示这个方法可能抛出某种异常
- 需要由方法的调用者进行异常处理
24. try-catch-finally 中哪个部分可以省略?
catch 和 finally 语句块可以省略其中一个,否则编译会报错。
package constxiong.interview;
public class TestOmitTryCatchFinally {
public static void main(String[] args) {
omitFinally();
omitCatch();
}
/**
* 省略finally 语句块
*/
public static void omitFinally() {
try {
int i = 0;
i += 1;
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 省略 catch 语句块
*/
public static void omitCatch() {
int i = 0;
try {
i += 1;
} finally {
i = 10;
}
System.out.println(i);
}
}
25. 常见的异常类有哪些?
异常非常多,Throwable 是异常的根类。
Throwable 包含子类 错误-Error 和 异常-Exception 。
Exception 又分为 一般异常和运行时异常 RuntimeException。
运行时异常不需要代码显式捕获处理。
下图是常见异常类及其父子关系:
Throwable
| ├ Error
| │ ├ IOError
| │ ├ LinkageError
| │ ├ ReflectionError
| │ ├ ThreadDeath
| │ └ VirtualMachineError
| │
| ├ Exception
| │ ├ CloneNotSupportedException
| │ ├ DataFormatException
| │ ├ InterruptedException
| │ ├ IOException
| │ ├ ReflectiveOperationException
| │ ├ RuntimeException
| │ ├ ArithmeticException
| │ ├ ClassCastException
| │ ├ ConcurrentModificationException
| │ ├ IllegalArgumentException
| │ ├ IndexOutOfBoundsException
| │ ├ NoSuchElementException
| │ ├ NullPointerException
| │ └ SecurityException
| │ └ SQLException