1.java.lang.Math
- Math.round(); // 四舍五入
- Math.ceil(); // ceil 天花板,向上取整
- Math.floor(); // 地板,向下取整
2.JMM和栈帧结构
a. java虚拟机内存模型
- 方法区:方法区它用于存储已被虚拟机加载的类信息、常量、静态常量、即时编译器编译后的代码等数据。方法区和堆一样是线程共享的
异常可能性:当方法区无法满足内存分配需求时,将抛出OutOfMemeryError异常- 堆:对于大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,当然我们后面说到的垃圾回收器的内容的时候,其实Java堆就是垃圾回收器管理的主要区域。堆是线程共享的
异常可能性:如果堆中没有内存完成实例分配,并且堆也无法再拓展时,将会抛出OutOfMemeryError异常- 运行时常量池:方法区的一部分,存在编译器生成各种字面量和引用
- 程序计数器:程序计数器(Program Counter Register)是一块较小的内存空间,它可以看做当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来取下一条需要执行的字节码指令,分支、跳转、循环、异常处理、线程恢复等基础功能都需要这个计数器来完成。程序计数器是线程私有的,每条线程都会有一个独立的程序计数器,唯一一个java规范中规定任何outOfMemoryError的区域
- 虚拟机栈:线程私有的。虚拟机栈描述的是java方法的内存模型:每个方法执行的时候会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、返回地址等。异常:线程请求的栈大于所允许的深度StackOverFlowError异常、如果扩展时申请到足够内存,会抛出outOfMemoryError异常
- 本地方法栈:与虚拟机栈的作用非常类似
- 直接内存:
b. 帧栈模型
3.各种溢出
a.java堆溢出
b.虚拟机栈和本地方法溢出
- 单个线程方法递归:方法不停的调用自己,导致线程请求的栈大于所允许的深度StackOverFlowError异常
- 不停的创建线程导致outOfMemoryError
c.方法区和运行时常量池溢出
- String.intern()方法导致运行时常量池内存溢出
- 借助CGlib使方法区内存溢出
![]()
d.本机直接内存溢出
4.二分查找(思考下二分排序、快排、countsort)
a.二分查找非递归方式实现:
public static int binarySearchII(int[] array,int key){
if(array.length<=0) return -1;
// if(array.length==1) return array[0]==key? 0: -1;
int left= 0;
int right=array.length-1;
while(left<= right){
int mid =(left+ right)/2;
if (array[mid]== key) {
return mid;
}else if(array[mid]> key){
right= mid-1;
}else {
left= mid+1;
}
}
return -1;
}
b.二分查找递归实现:
int BinSearch(int Array[],int low,int high,int key)
{
if (low<=high)
{
int mid = (low+high)/2;
if(key == Array[mid])
return mid;
else if(key<Array[mid])
//移动low和high
return BinSearch(Array,low,mid-1,key);
else if(key>Array[mid])
return BinSearch(Array,mid+1,high,key);
}
else
return -1;
}
5.动态代理和AOP
6.控制反转IOC
7.装饰者和适配器模式
8.“地球人都知道,Java有个东西叫垃圾收集器,它让创建的对象不需要像c/cpp那样delete、free掉,你能不能谈谈,GC是在什么时候,对什么东西,做了什么事情?”
- 什么时候
系统自身决定,不可预测的时间/调用System.gc()的时候。
eden满了minor gc,升到老年代的对象大于老年代剩余空间majorGc,full gc,- 对什么东西
从root搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。- 做什么事情
能说出诸如新生代做的是复制清理、from survivor、to survivor是干啥用的、老年代做的是标记清理、标记清理后碎片要不要整理、复制清理和标记清理有有什么优劣势等。
9.IOC(控制反转)/DI(依赖注入)
是一种降低对象之家耦合关系的设计思想。一般呢,我们在分层体系结构中,都是上层调用底层的接口,上层依赖于底层。而通过IOC的方式使得上层不再依赖底层接口。即采用一定的机制来选择不同的底层实现,完成控制反转。也就是由调用者来决定被调用者。IOC通过注入一个实例化对象来达到解耦合的目的。对象通过IOC容器来提供。例如要为一家卖茶的商店提供一套管理系统,在这刚开业时候只卖绿茶,以后可能还会卖红茶。
- 最普通的实现方式:得new对象,当绿茶改为红茶时得修改代码改为new红茶。不灵活,改动非常大
- 工厂模式:把创建对象委托给工厂,当绿茶改为红茶时只需要修改工厂方法就行了。只在一个地方改动
- 使用IOC设计思想:根据配置文件创建调用者对象,同时将被调用的对象放在调用者对象构造方法或者set方法中注入。
![]()
![]()
ApplicationContext xtx=new FileSystemXmlApplicationContext(“SpringConfig.xml”);
Sale s=(Sale)ctx.getBean(“sale”);- 通过IOC容器,开发人员不需要关注对象是如何被创建的同时增加新类也非常方便,只需要修改配置文件即可实现对象热插拔
- IoC容器可以通过配置文件来确定需要注入的实例化对象,因此非常便于进行单元测试
- 对象是通过反射机制实例化出来的,因此会对系统性能有一定影响
- 创建对象的流程变得复杂