2018/08/11面试总结(面试岗位:Java开发工程师)

Java部分:

  1. String、StringBuilder、StringBuffer的区别及优劣:

String:底层用char[]数组实现,并且数组内容不可改变(即用final修饰),因此不同的字符串即为不同的对象

如:String s = "1";s += 2;(此时s="12"),此时已经有两个字符串对象"1"、"12"

StringBuilder:非线程安全,底层用char[]数组实现(继承自AbstractStringBuilder),但可修改数组内容(未用final修饰),因此可以改变字符串内容(而不另外生成字符串对象)

当要追加的内容超过数组剩余空间时,需扩容数组,由于数组需要连续的地址空间,此处需整个复制原有数组内容,会消耗较多的时间和内存,因此使用的时候尽量预估一下会有多少字符,设置初始化char[]数组大小,避免过多扩容

StringBuffer:线程安全,底层用char[]数组实现(同StringBuilder一样继承自AbstractStringBuilder),同StringBuilder的区别,StringBuffer的方法是线程安全的,因此效率不如StringBuilder。

2.ArrayList和LinkedList的区别及优劣:

ArrayList:底层用Object[]数组实现,因此可实现随机访问(根据数组下标)访问速度较快,但是同StringBuilder类似,当数组长度不够时需扩容时或者删掉数组中某一元素时,需复制原有数组内容,比较消耗时间和内存,增删较慢

LinkedList:底层用双向链表实现,仅提供链表的头指针和尾指针,因此不可随机访问,但是增删时只需将需删除元素从链表中摘除,因此增删较快

注:具体实现可参考源码

3.什么时候需要用到迭代器?

容器类中都提供了迭代器,可通过迭代器访问容器中元素,当遍历集合中元素时,需改变集合中元素的个数(即增删集合中元素),可能会报错,此时需用到迭代器

而用迭代器,则可正常操作:

注:有一种设计模式叫迭代器模式,有兴趣的可以自己了解一下

4.java中有几种产生线程的方式?

继承Thread类:由于java的单继承机制,继承了Thread类之后不可再继承其他类,因此不建议用这种方式实现多线程,建议用第二种方式

实现Runnable接口:实现Runnable接口中的run()方法

线程池:可从已有的线程池中获取线程(第三种我没有答上来,因为个人感觉问的是如何产生线程,利用线程池是获取已有的线程)(线程池的好处,减少了产生线程的开销,可统一管理线程)

注:启动新线程的时候,应调用新线程的start()方法而非run()方法,具体如下例所示:

5.如何获取线程的终止状态(不是如何终止线程或者判断线程的状态)?

这个目前还没有想明白,后续有结果了会更新,知道的大神请指点。

6.java中如何加载类?

当时面试的时候只讲了两种,一种是用classLoader.loadClass(),另一种是Class.forName("class name"),具体例子见下图

重新查了一下资料,整理一下java虚拟机何时会加载类:

1.创建类的实例

2.访问类或者接口的静态成员变量

3.调用类的静态方法

4.反射(Class.forName("xxx.xxx.xxx"))

5.初始化一个类的子类(相当于对父类的主动使用),不过直接通过子类引用父类元素,不会引起子类的初始化

6.java虚拟机被标明为启动类的类(含有main方法的)

参考文章:https://www.cnblogs.com/zhguang/p/3154584.html

7.java垃圾回收机制,手动调用垃圾回收的时候,是否会立即回收?

在网上查的结果是并不会立即回收,具体回收时机参考文章:https://blog.csdn.net/yewei02538/article/details/52386642/

但是刚刚我看了源码,当调用System.gc()时,是会立即回收的,并不像上面文章讲的那样会先调用Runtime.getRuntime().runFinalization()

如下图:

可能是不同的jdk版本的不同处理策略,我看的版本是jdk1.8(换了一下1.7版本的,还是会直接调用Runtime.getRuntime().gc();)

8.见过或者用过哪些常用的设计模式?

设计模式有很多,几句话讲不完,可参考这个文章:https://blog.csdn.net/dean_hu/article/details/71195133

9.负载均衡策略?

这里简要列一下:http重定向、DNS负载均衡(将DNS服务器当作负载均衡服务器)、反向代理负载均衡(转发http请求)、IP负载均衡(LVS-NAT)、直接路由(LVS-DR数据链路层)、IP隧道(LVS-TUN)。

其实我也只是知道个大概,具体细节还有很多需要深究,详细一点的参考这篇文章:https://blog.csdn.net/wt725/article/details/58580315

10.HashMap和HashTable一个是线程不安全的(HashMap,速度较快),一个是线程安全的(HashTable,速度较慢),如何实现在线程安全的情况下,提交效率?

大致思路:将锁的粒度细化。访问元素的时候,判断元素会落到哪个位置,若之前是锁住整个table,仅锁住该位置为头结点的链表,其余位置的元素则可以正常操作。

数据库部分

1.mysql数据库加锁语句

Locking read(SELECT ... FOR UPDATE(排他锁) OR SELECT ... LOCK IN SHARE MODE(共享锁))

UPDATE以及DELETE语句通常会在他 扫描的索引所有范围上加锁忽略没有用到索引的那部分where语句

举个栗子:

CREATE TABLE `test` (
  `id` int(11) NOT NULL DEFAULT '0',
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

select * from test where id > 3 and name <'A' for update;

这条SQL语句的会将所有id>3的记录进行加锁,而不是id>3 and name <'A' 进行加锁,因为name上面没有索引

详细可参考文章:http://www.fordba.com/locks-set-by-different-sql-statements-in-innodb.html

2.redis有哪些数据结构?

redis可以存储键和五种不同类型的值之间的映射:

  • String字符串
  • List列表
  • Set集合
  • Hash散列
  • Zset有序集合

详细可参考文章:https://blog.csdn.net/fan510988896/article/details/71730696

3.mysql数据库建表时使用过哪些存储引擎(如事务型或非事务型,innoDB等)?

MySQL存储引擎在另外一篇博客中介绍:https://blog.csdn.net/weixin_38823568/article/details/81702397

其他部分

1.对http协议的了解,http三次握手

Http使用的TCP协议,实际是TCP的三次握手:

  • 客户端发送请求到服务端请求建立连接(SYN包)
  • 服务端收到请求后,发送自己的连接请求(SYN)以及对收到的客户端请求包的确认(ACK),即SYN+ACK包
  • 客户端收到服务端的SYN+ACK包,向服务器发送ACK确认

以及四次断开连接过程,具体可见下图:

图片来源及参考文章:https://blog.csdn.net/yanxinrui0027/article/details/70243665

2.对https的了解?

个人对Https并没有太多了解,上网查了一下,感觉这篇文章写的挺通俗易懂的:https://www.cnblogs.com/xinzhao/p/4949344.html,后续应该会更详细的研究一下。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值