Java常见面试题整理1(银行)(答案正在整理中)
1.JVM运行时内存
java虚拟机在执行Java程序的过程中会把它管理的内存划分为几个不同的数据区域。
线程私有:程序计数器、虚拟机栈、本地方法栈
线程共享:堆、方法区(JDK1.8之后用元空间metaspace代替了方法区)、(直接内存(非运行时数据区的一部分))
(1) 程序计数器
占用内存很小,是唯一一个不会出现outOfMemoryError的内存区域。
功能:1)字节码解释其通过改变程序计数器的值来依次读取指令,实现代码的流程控制。例如:顺序执行、选择、循环、异常处理。
2)在多线程的情况下,程序技术去用于记录当前线程的位置。线程切换回来的时候能够知道执行到哪儿了。
(2)虚拟机栈
虚拟机栈描述的是Java方法执行的内存模型,方法调用的数据都是通过栈传递的。
虚拟机栈是由一个个栈帧组成的,每个栈帧都包括:局部变量表、操作数栈、动态链接、返回值。
局部变量表主要存放了编译期可知的各种数据类型,对象引用。
会出现outOfMemoryError和StackOfMemoryError。
outOfMemoryError:如果Java虚拟机堆中没有空闲内存,并且垃圾回收器也无法提供更多的内存的话,会抛出outOfMemoryError。
StackOfMemoryError:如果虚拟机的内存大小不允许动态扩展,当线程请求的栈的深度超过当前VM栈的最大深度,将抛出StackOfMemoryError。
(3)本地方法栈
和VM栈的作用相似。VM栈为虚拟机执行Java方法服务,本地方法栈为虚拟机使用到的native方法服务。
栈帧内容和可能发生异常同VM栈。
(4)堆
Java虚拟机所管理内存最大的一块。这个区域的唯一目的就是存放对象实例,几乎所有的对象实例和数组都在这里分配内存。堆是垃圾收集器管理的主要区域,因此也被称为GC堆。(垃圾收集器采用分代垃圾收集算法)Java堆可以细分为新生代和老年代(MaxTenuringThreshold设置年龄阈值),更加细致的有:Eden空间、from Survivor、to Survivor(便于更好的回收内存、更快的分配内存)
堆中容易出现outOfMemoryError
(5)方法区
方法区用于存储已经被虚拟机加载的类的信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也被称为永久代,永久代是Hotspot的概念,方法区是Java虚拟机规范的一种定义,一种规范,而永久代是一种实现。
2.集合排序怎么实现
java集合的工具类Collections中提供了两种排序的方法,分别是:
Collections.sort(List list)
Collections.sort(List list,Comparator c)
第一种称为自然排序,参与排序的对象需实现comparable接口,重写其compareTo()方法,方法体中实现对象的比较大小规则;
第二种叫定制排序,或自定义排序,需编写匿名内部类,先new一个Comparator接口的比较器对象c,同时实现compare()其方法; 然后将比较器对象c传给Collections.sort()方法的参数列表中,实现排序功能;
参考https://www.cnblogs.com/huangjinyong/p/9037588.html
3.泛型是什么,作用?
在JDK的框架集合中,泛型被非常广泛地使用。
泛型,即“参数化类型”。顾名思义,就是将原本具体的类型 参数化 。可以将类型也定义成参数形式,然后在使用/调用时传入具体的类型。
在Java中实现泛型机制的目标是为了可以把发现 bug 的时机提前到编程源码时,而不是运行时。如果在编译时就可以发现 bug ,就可以节省大量的调试Java程序的时间,因为编译错误可以比较容易和比较快速地被发现和修复。而且,泛型仅仅只存在于编译时。
4 线程创建方式
Java 使用 Thread 类代表线程,所有的线程对象必须是 Thread 类或其子类的实例。Java 可以用四种方式来创建线程,如下:
①继承 Thread 类创建线程没有返回值;
②实现 Runnable 接口创建线程没有返回值;
③实现 Callable 接口,通过 FutureTask 包装器来创建 Thread 线程有返回值;
④线程池:使用 ExecutorService、Callable、Future 实现有返回结果的线程有返回值。
5种状态:
5.array,arrayList的区别,可以存储基本类型吗
1.存储内容比较:
Array 数组可以包含基本类型和对象类型;ArrayList 只能包含对象类型。
2.空间大小比较:
Array 数组的空间大小是固定的,所以需要事前确定合适的空间大小。
ArrayList 的空间是动态增长的,而且,每次添加新的元素的时候都会检查内部数组的空间是否足够。
3.方法上的比较:
ArrayList 方法上比 Array 更多样化,比如添加全部 addAll()、删除全部 removeAll()、返回迭代器 iterator() 等。
arrayList不可以存储基本类型
原文链接:https://blog.csdn.net/g1998i/article/details/79663976
6.JDK、JVM、JRE 三者关系JDK>JRE>JVM
JVM:Java虚拟机,有针对不同操作系统的特定实现,是java“一次编译,多次运行”的关键所在;
JRE:JDK + Java核心类库
JDK: JRE + Java开发工具(java.exe;javac.exe;javadoc.exe)
7.String StringBuffer StringBuilder区别
1.可变性
String类中使用final关键字修饰字符数组保存字符串:private final char value[],所以是不可变的;
StringBuilder和StringBuffer都继承自AbstractStringBuilder,其中也是使用字符数组保存字符串,但是没有用final修饰,所以是可变的;
StringBuilder和StringBuffer的构造方法都是调用AbstractStringBuilder的构造方法实现的。
2.线程安全性
String中对象不可变,可以认为是常量,线程安全;
AbstractStringBuilder定义了一些字符串的基本操作(append,insert,indexOf),StringBuffer对方法加了同步锁,线程安全;
StringBuilder没有加同步锁,所以非线程安全;
在底层实现上,StringBuffer比StringBuilder多了Synchronized修饰符
3.性能
每次对String进行改变都会生成新的对象,将指针指向新的对象;
StrinngBuffer和StringBuilder对自身进行操作,相同情况下StringBuilder会比StringBuffer获得10%-15%的性能提升。
8.构造函数
9.final finally 的区别
10.数据库脏读是怎样产生的
11.Servlet的生命周期
12.Cookie和Session的区别
13.NIO、BIO原理
14、ArrayList和LinkedList区别 插入哪个更快
(1)数据结构:ArrayList是动态数组的数据结构实现;LinkedList是双向链表的数据结构实现。
(2)随机访问效率:ArrayList》LinkedList;LinkedList是线性的数据存储方式,需要移动指针从前到后依次寻找
(3)增加和删除效率:非首尾
15.异常,举出三个运行时异常的例子
16.对象的创建方式
一共有5种:
1.使用new关键字
这是最常见也是最简单的创建对象的方式。
通过这种方式,我们可以调用任意的构造函数(无参的和带参数的)。
例如
Employee emp1 = new Employee();
2.使用Class类的newInstance方法
我们也可以使用Class类的newInstance方法创建对象。
newInstance方法调用无参的构造函数创建对象。
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance(); //或者 Employee emp2 = Employee.class.newInstance();
3.使用Constructor类的newInstance方法
java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。
我们可以通过这个newInstance方法调用有参数的和私有的构造函数。
Constructor<Employee> constructor = Employee.class.getConstructor(); Employee emp3 = constructor.newInstance();
> 方法2、3就是反射机制
4.使用clone方法
无论何时我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
要使用clone方法,我们需要先实现Cloneable接口并实现其定义的clone方法。
Employee emp4 = (Employee) emp3.clone();
5.使用反序列化
当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。在反序列化时,jvm创建对象并不会调用任何构造函数。
为了反序列化一个对象,我们需要让我们的类实现Serializable接口
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj")); Employee emp5 = (Employee) in.readObject(); 261: invokevirtual #118 // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object;
除了第1个方法,其他4个方法全都转变为invokevirtual(创建对象的直接方法)
第一个方法转变为两个调用,new和invokespecial(构造函数调用)。
参考自:https://www.cnblogs.com/wxd0108/p/5685817.html
补充:Java类的创建过程?
1.类加载检查
当虚拟机遇到类的创建指令时,首先会去检查这个指令的参数,能否在常量池中找到这个类的符号引用,并且检查这个符号引用是否已经被加载、解析和初始化过,如果没有,就要先执行相应的类加载过程。
2.分配内存
虚拟机要为新生对象分配内存,所需内存大小在加载完成后就能能够确定,为对象分配空间等同于将Java堆中的一块确定大小的内存划分出来。分配方式有两种:指针碰撞 和 空闲列表 ;
分配方式由Java堆是否规整决定;即由垃圾收集器是否带有压缩整理功能决定。
3.初始化零值
虚拟机将分配到的内存空间都初始化为零值(不包括对象头),保证了Java代码不赋初值就可以使用。
4.设置对象头
将元数据信息、对象的哈希码、gc分代以及年龄等问题存放在对象头中。
5.执行init方法
现在从虚拟机的角度来看对象已经产生,但是从java程序来看,所有的字段都还是零,所以需要执行init方法,将对象按照程序员的意愿进行初始化。
17.Object的方法
18.线程同步方式有哪些
19.jdbc
20.抽象类与接口的区别
1.实现:抽象类用extends;接口用implements
2.构造函数:抽象类支持,接口没有
3.main函数:抽象类有,接口没有;
4.实现数量:抽象类1个,接口多个;
5.访问修饰符:接口 public(只能有static、final变量),抽象类 任意(除了private)
21.TCP与UDP区别
22.TCP的首部长度
23.TCP端口号
24.数据库锁
MySQL的锁机制比较简单,最显著的特点就是不同的存储引擎支持不同的锁机制。
MySQL大致可归纳为以下3种锁:
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
25.sleep和wait区别
(1)sleep和wait都可以暂停线程的执行;
(2)sleep()方法没有释放锁,wait()方法释放了锁;
(3)wait()通常被用于线程间通信;sleep()通常用于暂停执行;
(4)wait()调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的notify()或者notifyAll();sleep()调用后,线程会自动苏醒,或者可以使用wait(longtimeout)超时后线程自动苏醒。
26.final finally finalize的区别
27.讲讲Spring Boot
- jdbc连接数据库
29.tcp的三次握手
30.数据库事务特性
- http和https的区别
32.讲讲 HashMap 底层结构实现
33.ConcurrentHashMap 底层实现
34.数据库左连接右连接有什么区别?关键字是什么?
35.数据库的优化