java面试题总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java面试题总结相关的知识,希望对你有一定的参考价值。

1、spring aop的实现原理:
  spring提供了两种方式来生成代理对象:JDK原生的JDKProxy和CgLib,具体使用哪种方式是有AOPProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口就用jdkProxy,否则就用CGLIb来生成代理。
2、JDK原生动态InvocationHandle是JDK动态代理的核心。
3、CunrrentHashMap的size是如何计算统计的:
  计算的时候是先统计每个分片(默认16个分片)的总数据量。如果在统计过程中,容器的count发生变化就用加锁的方式获取大小。默认重试两次不加锁的获取,两次获取都失败,则加锁获得。监控count的变化与否,是有个成员变量modCount对比,每次分片上的add或者remove时候,该值都会相应的增加或者减少。
4、ArryList的初始化大小为10(即调用不传入参数的构造方法),所以如果在使用中知道容量最好能直接初始化,这样就避免扩容的问题。
  扩容规则;发现空间不够用,就去扩容。
  扩容大小规则:扩容后的大小= 原始大小+原始大小/2 + 1。(例如:原始大小是 10 ,扩容后的大小就是 10 + 5+1 = 16),ArrayList底层是数组实现,有大小限制,理论上最大为Integer.MAX_VALUE=2的31次方-1,该大小是规范隐含的限制。Java数组的length必须是非负的int,所以它的理论最大值就是java.lang.Integer.MAX_VALUE = 2^31-1 = 2147483647。
5、LinkedList是一个双向链表,没有初始化大小,也没有扩容的机制,就是一直前面后面增加即可,理论上可以无限扩大,。
6、HashMap初始化大小为16.扩容因子默认0.75,可以直接制定初始化大小和扩容因为。当当前的容量超过了扩容因子的时候会触发扩容,容量扩容一倍。即如果默认是16,然后容量存入12,12/16=0.75会触发扩容,扩容到32.
7、事务的四大特性:ACID(原子性、持久性、一致性、隔离性)。事务的隔离级别
   脏读:就是一个事务修改了数据没有提交,另一个事务读取了没有提交事务的数据。
   不可重复读:就是一个事务在读取的过程中读取到另一个事务提交的数据了。
   幻读:一个事务多次查询中返回的个数不一样,即第一次查询个数为5个,另一个事务提交了数据。再次查询个数多与5(有可能少于5也是幻读的概念),就出现了幻读的数据。
   幻读和不可重复读都是查询到了另一个事务提交的数据。区别是不可重复读是针对同一条数据可能不同,幻读是针对数据的个数。

8、事务的隔离级别:未提交读、提交读、可重复读、序列化。隔离级别依次升高。
        未提交读:就是不提交其他事务就可以读,是最弱的隔离级别。现实应用中基本很少用到。该级别可导致脏读、不可重复读、幻读。
        提交读:提交了事务别的事务才能看到。该级别是大多默认应用的隔离级别。也是oracle和sqlServer默认的隔离级别。该级别可以避免脏读。但是导致了不可重复读和幻读。
        可重复读:是mysql的默认隔离级别。就是不管别的事务插入了数据还是删除了数据并提交事务。在当前事务中读取的数据始终是一样的。这就导致了一个问题,其他事务修改了数据量。但是我当前事务查询的还是旧的不准确的数据量。这就是该事物的弊端。可以导致幻读。
        序列化:是最高的隔离级别。 他其实是在每行数据上加锁。保证了数据读的准确性。但是因为锁的原因效率最低。实际不怎么应用。
9、volatile不能保证操作的原子性但是保证了内存的可见性。即对不同线程之间访问的数据都是最新的。想要保证原子性就必须使用Atomic类。这种在硬件层面上保证了读写是原子性的,不像普通的int类型的是分两步执行的(先读取变量值,然后在++)
10、编写wait方法写在if或者循环内调用啊:应该使用循环,因为当前条件不满足的时候会等待,所以用循环。
11、多线程之间的伪共享:其实多线程也就是多cpu或者多核心中cpu都有自己的一份缓存。写入的操作是通过cpu写入到主存的过程。主存才是真正的共享。so多线程之间的cpu缓存是伪共享。
12、线程局部变量:通过ThreadLocal共享,但是共享就有个不释放内存泄漏的问题需要关注。
13、java sleep和wait的区别:sleep是短暂睡眠不会释放锁,wait会释放锁让给其他线程使用。
14、java应该用什么表示价格。看对精度的要求,精度高就用BigDecimal,一般就用double即可。
15、a = a + b 与 a += b 的区别 a+=b安全不会报错结果就是a的类型。a=a+b转换成int相加会报错。
16、3*0.1 == 0.3 结果为false 因为java是浮点数不能精确的标识出来。
17、int 和Integer使用过程中,Integer会更加占用资源
18、java String是不可变的一个原因是设计者认为使用的频率很大,设计不可变便于共享并安全。
19、java swich能使用string吗,jdk1.7以后可以,其实内部底层是吧string转为hashCode实现的。
20、解释 Java 堆空间及 GC? java命令启动java进程的时候会分配内存,创建对象的时候会在堆内存中分配空间,GC主要回收堆内存中无引用的空间的垃圾收集器。
21、你能保证GC执行吗?不能,通过硬编码System.gc()可以执行,但是不保证执行。看它心情。
22、java堆和栈区别。堆是放共享的对象的可以供Gc回收。栈是方法和局部变量的地方的,是线程独有的,用完即释放,堆需要自己通过GC回收。
23、java static final transient关键字区别:
    static:修饰变量、方法、代码块,static的修饰的是属于类的不属于实例的。
    final:中文是不可变的,可以修饰类、方法、变量。修饰类时候类不可继承,修饰方法不允许重写、修饰变量的时候该类不可变。
    transient:该关键字用在java序列化中,用该关键字修饰的变量java序列化的时候会忽略。
    通常:static和fianl是一块使用,因为static仅仅存在一份。final是不可变。这样就保证了不可变的数据仅仅保留了一份。
25、增强for循环 foreach是语法糖,集合类的想要使用必须实现Iterable接口,因为他底层是按照Iterable迭代器遍历的。而数组没有实现迭代器接口,他底层是循环遍历数据引用实现的。即增强for循环都是调用底层去实现的。
26、hashtable和hashmap的区别,Hashtable是旧的api遗留的,他的所有方法都是synchronized,所以是线程安全的,但是效率差。hashtable和hashmap的实现原理是一样的,都是通过hash表实现,然后有entry静态类(可以理解为单向链表并保存了key和value)进行扩展。jdk1.8的hashmap是用数组+链表+红黑树(jdk1.8增加的)进行实现的,链表长度大于8的时候自动转换成红黑树,TreeMap基于红黑二叉树实现。保证了顺序。
27、hashset的底层实现原理是hashmap。仅仅使用了hashmap的key。
28、CopyOnWrite是在写的时候加锁拷贝一份数据到新数据进行写操作,写完之后把引用指向新的修改完的数据。用于读多写少的并发场景。缺点就是占用内存大,不能保证实时的一致性,只能保证最终一致性。














































以上是关于java面试题总结的主要内容,如果未能解决你的问题,请参考以下文章

java开发面试题:spring面试题总结

Java面试题总结 14Redis面试题总结(附答案)

面试总结目录

Java面试题全集(上)(中)(下) (转)+自己总结

Java开发基础面试题,java研发工程师年终总结

java经典面试题总结