《面试小抄》之Java基础篇下49问与答本文包含了String、包装类型、反射、泛型、序列化、异常和IO的常见面试题
serial 单线程: 必须stw 复制算法
ParNew:Serial收集器的多线程版本,也需要stop the world,复制算
Parallel Scavenge: 复制算法的收集器 并发的多线程收集器 可以控制吞吐量
Serial Old: Serial收集器的老年代版本,单线程收集器,使用标记整理算法
Parallel Old : 标记-整理算法。
CMS: 标记清楚: 初始标记 并发标记 重新标记 重新标记 并发清楚 收集结束会产生大量空间碎片;
G1: 标记整理算法+复制:面向服务器
加载: 1 通过类全限定性类名获取该类的二进制流 2 降二进制流的静态存储结构转为方法区运行时数据结构 3 在堆中为该类生成一个class文件
打破双亲委派机制
继承:classLoader 类 loadCLass方法和findclass方法
字符串常量池:
- 在jdk6中,常量池的位置在永久代(方法区)此时常量池中存储的是对象。
- 7 在堆中 此时,常量池存储的就是引用了
- jdk8中,永久代(方法区)被元空间取代了。
字节流如何转为字符流?
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。
tale 指针碰撞
myisam:
.frm: 存储表定义
.myd(MYData):存储数据
.MYI(MYindex):存储引擎
innodb:
.frm:存储表定义
.idb:存储数据和索引,在同一个文件中
synchronized 和 volatile 的区别是什么?
synchronized 表示只有一个线程可以获取作用对象的锁,执行代码,阻塞其他线程。
volatile 表示变量在 CPU 的寄存器中是不确定的,必须从主存中读取。保证多线程环境下变量的可见性;禁止指令重排序。
区别
volatile 是变量修饰符;synchronized 可以修饰类、方法、变量。
volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变量的修改可见性和原子性。
volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。
volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。
volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用 synchronized 关键字的场景还是更多一些。
局部变量成员变量
一:在方法中声明的变量,即该变量是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因
在方法中声明的变量可以是基本类型的变量,也可以是引用类型的变量。
(1)当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在方法栈中
(2)当声明的是引用变量时,所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在方法的栈中,该变量所指向的对象是放在堆类存中的。
二:在类中声明的变量是成员变量,也叫全局变量,放在堆中的(因为全局变量不会随着某个方法执行结束而销毁)。
同样在类中声明的变量即可是基本类型的变量 也可是引用类型的变量
(1)当声明的是基本类型的变量其变量名及其值放在堆内存中的
(2)引用类型时,其声明的变量仍然会存储一个内存地址值,该内存地址值指向所引用的对象。引用变量名和对应的对象仍然存储在相应的堆中
4.如何保证订单重复提交的问题(当发生网络延迟等情况)
lz:楼主只回答了前端校验和后端校验具体其他操作不是很清楚,下面答案引用自百度百科只列举几个经典的(力争为园友提交较可信的答案)
更详细的答案可以参考:http://www.bkjia.com/jingyan/471187.html
1:在前端进行校验,当表单提交后,把提交按钮置灰
2:表单提交后进行页面重定向,转到处理结果页面。
3:在session中存放一个标识符(当表单数据被请求时,在session中生成一个标识符放在表单隐藏域中,当后端处理表单数据时,检查标识符是否存在,如果存在则表明第一次提交并从session中清除标识,如果不存在则表明重复提交)
4:在数据中添加约束
从永久代(PermGen)到元空间(Metaspace)
为什么要做这个转换?总结以下几点原因:
-
1、字符串存在永久代中,容易出现性能问题和内存溢出。
-
2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
-
3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
-
4、Oracle 可能会将HotSpot 与 JRockit 合二为一。
sleep() 和 wait() 的区别?
1、sleep() ⽅法正在执⾏的线程主动让出 cpu(然后 cpu 就可以去执⾏其他任务),在 sleep 指定时间后 cpu 再回到该线程继续往下执⾏(注意:sleep ⽅法只让出了 cpu,⽽并不会释放同步资源锁);⽽ wait() ⽅法则是指当前线程让⾃⼰暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进⽽运⾏,只有调⽤了 notify() ⽅法,之前调⽤ wait() 的线程才会解除 wait 状态,可以去参与竞争同步资源锁,进⽽得到执⾏。(注意:notify 的作⽤相当于叫醒睡着的⼈,⽽并不会给他分配任务,就是说 notify 只是让之前调⽤ wait 的线程有权利重新参与线程的调度);
2、 sleep() ⽅法可以在任何地⽅使⽤,⽽ wait() ⽅法则只能在同步⽅法或同步块中使⽤;
3、 sleep() 是线程类(Thread)的⽅法,调⽤会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间⾃动恢复;wait() 是 Object 的⽅法,调⽤会放弃对象锁,进⼊等待队列,待调⽤ notify()/notifyAll() 唤醒指定的线程或者所有线程,才会进⼊锁池,不再次获得对象锁才会进⼊运⾏状态。