java深入源码级的面试题(二)
哪些情况下的对象会被垃圾回收机制处理掉?
1、对象无引用,只有自身一个节点, 当触发GC时就会被标记清除
2、对象不是强引用,属于弱引用、虚引用,或者对象本身就是空对象时,当内存不够时就会被GC掉
讲一下常见编码方式?
ASCII码、Unicode、utf-8 等
utf-8编码中的中文占几个字节;int型几个字节?
中文占3到4个字节 int 占 4个字节
静态代理和动态代理的区别,什么场景使用?
静态代理:自己编写代理类,再编译期就完成。一般用于原对象的功能扩展,但又不会破坏原来接口协议格式
动态代理:一般基于系统Proxy,调用系统方法实现代码在运行期动态生成需要的代理类。这样相对而言比静态代码要灵活,实际项目中使用的也最多,不会造成功能对象和代理对象的紧耦合
Java的异常体系
java.lang.Throwable为所有异常的超类:分为错误Error和异常Exception两大类:
异常的种类也有很多,一般分为运行时异常RuntimeException和非运行时异常,一般的数组越界、空指针等都是运行时异常;而数据库、文件读写出现的异常基本都是非运行时异常,代码不做处理编译通不过。
一般异常处理流程:
try{
//可能发生异常的地方
}
catch(Exception e){
//抛出异常
}
finally{
//不管发没发生异常都要执行
}
谈谈你对解析与分派的认识。
解析:在编译阶段就直接把一部分方法的符号引用转化为直接引用,方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的。换句话说,调用目标在程序代码写好、编译器进行编译时就必须确定下来
分派:针对重写、多态的方法,在运行期去确定该动态调用那个方法
从java 虚拟机内部原理入手分析解析和分派:
https://www.jianshu.com/p/355ae3bcec41
修改对象A的equals方法的签名,那么使用HashMap存放这个对象实例的时候,会调用哪个equals方法?
该对象超类Object 类的equals方法
Java中实现多态的机制是什么?
父类引用指向子类对象
如何将一个Java对象序列化到文件里?
ObjectOutputStream obj=new ObjectOutputStream(new FileOutputStream("xxx.txt"));
obj.writeObject(new Pepole("name",yangyong);
obj.close();
说说你对Java反射的理解
java反射提供了一种代码运行时动态改变其属性的可能,我们写的所有java文件经过编译阶段都会生成class文件,然后进入JVM虚拟机进行class加载链接运行,然而反射就是把我们JVM中运行calss文件的各种属性、变量、方法等反射成相应的对象,让我们可以对其进行修改
获取反射对象可以:getClassLoader() ,getClass()
反射会消耗系统性能,我们不应该滥用反射
说说你对Java注解的理解
java中注解类似于生活中标签的作用,就是用我们的标签(元数据),对想标注的物品(对象、方法)进行标注,注入我们定义好的属性的值,当我们需要的时候进行获取解析(可以是编译器生成字节码,或者通过反射获取注解对象)时就可以知道这个东西代表什么东西,有那些属性
说说你对依赖注入的理解
依赖注入:张三写代码---->代码开放接口,注入一个程序员即可以完成,即实现一个程序员的引用指向一个张三实例,然后把所创建的对象设置到写代码任务中, 这个过程就是依赖注入,完成了一个控制反转
很多优秀的框架都使用的依赖注入,如butterkife、dagger2 .
butterkife中我们只需要把我们的控件ID通过@BindView注入进去完成了控件初始化
dagger2中:
DaggerXXXComponent
.builder()
.appComponent(appComponent)
.controlCarModule(new XXXModule(this))
.build()
.inject(this);
这几行代码也是一个依赖注入,把appComponent、XXXModule、this注入编译期生成好的DaggerXXXComponent类中,以提供我们整个dagger2需要的数据源
说一下泛型原理,并举例说明
泛型让编程人员能够使用类型抽象,通常用于集合里面,可以使用通配符:
上界通配符
下界通配符
方法参数集合通配符List>
对类型的抽象,更够使代码为通用,我们可以定义泛型类、泛型方法、含通配符的列表等
Java中String的了解
【java深入源码级的面试题(二)】String是常量,所以储存肯定是再常量池中,如果是String对象那又不一样,那会存于堆中
https://www.jianshu.com/p/2f209af80f84
操作对比:
String a="hello ";
String b=a+"world";
String c="hello "+"world";
String d="hello world";
b==d //false
c==d //true
String为什么要设计成不可变的?
1、线程安全
2、原子操作
3、对象变化得到了避免
Object类的equal和hashCode方法重写,为什么?
因为当把Object对象放到集合中时,通过Equals比较对象,不做处是理还会出现重复的问题,根据hash原则,对象的映射地址是根据算法生成,因为hash碰撞的存在,即两个不同的对象hash地址可能一样的情况,这样在hash地址相等的情况下还需要去重写equal方法进行比较
有两种办法可以解决这个问题,第一个就是重写Object类的equal和hashCode方法;第二个就是把对象转换成String再放入集合中,因为String类源码已经重写了这两个方法
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 深入理解Go之generate
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- 【1057快报】深入机关,走下田间,交通普法,共创文明
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- 生发知识,带你深入了解
- Android事件传递源码分析