Android面试技术干货面试题

Java基础面试题解析(一)

2018-03-15  本文已影响521人  随风_04a7


冰冻三尺非一日之寒

        在面试一些比较大一点的公司时候,时长会碰到有Java面试(题)部分,往往做Android的小伙伴在平时可能较少关注Java基础概念这一块,措手不及之下往往会懵逼,或者有点印象但又似是而非。冰冻三尺非一日之寒,关键还是在于平时的整理与积累,说做就做,写下此文。

主要内容:

1、Java中堆、栈、堆栈的区别

2、简要叙述Java GC机制

3、int、char、long各占多少字节数

4、float、double的区别?为什么会造成精度丢失

5、String、StringBuffer、StringBuilder区别

6、java中==和equals和hashCode的区别

8、final,finally,finalize的区别

int与integer的区别

Java中堆、栈、堆栈的区别

先来一张JVM内存模型,图片源自JVM内存模型与垃圾回收

再看一下Java内存区域划分:

从上图可以得知,JVM中最主要的存储区域划分就是方法区(Method Area)、栈(Stack)与堆(Heap),其实堆栈实际上仍是栈,只是翻译过来的叫法差异。主要区别如下:

1、生命周期, JVM将进程所管理的区域划分为线程私有区域,以及线程共有区域。而栈即线程私有,依赖用户线程的启动/结束而创建/销毁,堆即线程共有,随虚拟机的启动/关闭而创建/销毁;

2、用途,虚拟机栈用于存储局部变量表(基本数据类型、对象引用、字节码指令地址)、操作数栈、方法出口等信息,本地方法栈无非就是存储Native方法的相关信息;堆主要存储对象的实例,由JVM动态分配,垃圾回收机制也主要是针对这一存储区域;

3、异常情况,当方法运行的时候,请求新建栈帧时,栈所剩空间小于战帧所需空间时会抛出StackOverFlowError,通常出现在循环语句块与递归调用的时候;堆空间不足会抛出OutOfMemoryError;

简要叙述Java GC机制


触发时机:新生代中eden 满了minor gc,升到老年代的对象大于老年代剩余空间full gc,或者小于时被HandlePromotionFailure参数强制full gc,系统会在不可预测的时间调用System.gc()函数,不由程序员控制;

作用对象:超出了作用域或引用计数为空的对象;从gc root开始搜索找不到的对象,而且经过一次标记、清理,仍然没有复活的对象;

主要工作:删除不使用的对象,回收内存空间;运行默认的finalize,当然程序员想立刻调用就用dipose调用以释放资源如文件句柄,JVM用from survivor、to survivor对它进行标记清理。

引起现象:“stop-the-world”,Stop-the-world会在任何一种GC算法中发生,是因为GC本身也是属于JVM中的一组进程,会占用一定的资源,运行时会争抢CPU的时间片,当进程得不到CPU的时间片的时候就会被挂起。那么当GC进程拿到CPU的时间片的时候,当前进程(应用程序)也就处于暂停状态,导致的现象就是应用程序卡顿。

优化: 1、尽早释放无用对象的引用;

            2、对象缓存尽量避免强引用,可适当使用WeakReference;

            3、避免频繁创建对象;

            4、避免手动调用System.gc();

            5、避免使用finalize(),提升GC效率;

int、char、long各占多少字节数

float、double的区别? 为什么会造成精度丢失

谈论这个问题首先要看看浮点数在计算机中是如何表示的,计算机只能识别0和1,因此毫无疑问float和double也是0和1的二进制数字表示的。浮点数在二进制编码中由三部分组成,分别是Sign-Bit、Biased-Exponent、Significant。

sign-bit:符号位,也叫数符,仅占一位,表示正负,0为正,1为负;

biased-exponent:指数位,也叫阶码,主要是表示十进制向二进制转换时进行的移位运算,值为移动位数+偏移值(详情参考:浮点数与二进制的转换);

significant:基数位,也叫尾数,规格化后的二进制的小数部分;

不同点:1、在内存中占有的字节数不同;

2、有效数位不同,即表示的数值范围不一样;

3、CPU对两种数值类型处理速度不一样,float一般快于double。(仅针对大量浮点数运算可以体现出明显差异)

相同点:都不能准确表示范围内的某些数值,仅能精确表示m*2e的数值,

注意事项:1、由于浮点数不能精确表示其范围内的某些数值,会引起精度丢失的现象,尤其是在金钱计算方面,可以使用精度更高的BigDicemal,或者和后端统一使用整型进行精确运算;

2、主意float和double所占的字节数大小,尤其是涉及大量运算的时候,还需主意运算效率带来的影响。

String、StringBuffer、StringBuilder区别

1、String是字符串常量,其余二者都是字符串变量,因此要改变String实例,其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,效率比其余二者低;

2、StringBuffer是线程安全的,而StringBuilder是非线程安全的,因此在单线程环境下StringBuilder效率高于StringBuffer,不考虑线程安全优先使用StringBuilder;

3、String适用于少量的字符串操作的情况,StringBuilder适用于单线程下在字符缓冲区进行大量操作的情况,比如循环中频繁进行字符串拼接。

java中==和equals和hashCode的区别

1、“==”是运算符,常用于比较基本数据类型是否相等,若是引用类型比较,则比较他们的内存地址;

2、equals是Object类的方法,用于比较两个对象是否相等,默认Object类equals方法的实现就是“==”,跟==的结果一样;

3、hashcode()也是Object类的一个方法,返回该实例的hash码,hash码主要用于散列对象作为KEY来标示这个对象的存储位置,功能类似索引一样能够快速查找提取对象;

4、保证元素的唯一性,必须同时覆盖hashCode和equals才行。

final,finally,finalize的区别

Final修饰的类,不能被继承,其中所有方法不能被重写,所以不能同时使用abstract修饰类(abstract修饰的类是抽象类,抽象类是用于被子类继承的,否则没有意义);Final修饰的方法不能被重写,修饰的变量不能被修改。

Finally是属于try-catch语句中的一部分,不管有没有异常发生,都会被执行,通常用于资源的释放。

Finalize,Java虚拟机在垃圾回收之前会先调用垃圾对象的finalize方法用于使对象释放资源,一般不显示调用,由于GC触发是不确定的,因此该方法调用的时机也是不确定的。

int与integer的区别

1、Integer是int提供的封装类,而int是Java的基本数据类型;

2、Integer默认值是null,而int默认值是0;

3、声明为Integer的变量需要实例化,而声明为int的变量不需要实例化;

4、Integer变量实际上是对一个Integer对象的引用,而int变量直接存储数值;

基于第四点需注意:

A、两个通过new生成的Integer变量永远是不相等;

B、Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true;

C、非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同;

D、对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false;

        暂时写到这里,篇幅太长不便于阅读,参考了不少博客以及相关书籍,尤其是关于JVM内存结构、GC机制这一块,整整看了一下午,感谢相关作者,谬误之处也欢迎各位小伙伴指正^-^^-^

参考博文:

JVM GC 机制与性能优化

上一篇下一篇

猜你喜欢

热点阅读