趣链科技一面(电面)

约的是下午3点,结果下午6点才打来,没有想到的是面试官是女孩。

她:(上来就问)请你介绍一下你自己

我:……人生第一面,有点紧张……我来自湖北师范大学……我是湖北师范大学的大三在校生,我是大一下开始学Java的,到现在差不多两年了,我的专业是信息工程,是比较偏硬件的,但是我对软件比较感兴趣,所以在学校的实验室自学的Java。

她:哦,好的。我看你的博客上用的是C语言(被打断)

我:那是因为我最近在学数据结构和算法。而数据结构用C语言实现比较贴近结构本身,所以用的C语言,而后来学算法就转用Java了,因为封装性较好,不用写很多重复代码

她:哦,好的。那你除了Java还会其他语言吗?

我:额……我除了Java就只会一些C语言基础

她:哦,好的。那你知道Object类吗?其中定义了哪些方法?

我:hashcode、toString、getClass、wait、notify……额……我一下说的上来的就这些

她:你知道equals和等号的区别吗?

我:如果是基本类型,等号比较的是数值。如果是引用类型,等号比较的是地址。而equals如果没有重写的话默认比较的是地址,你可以重写来自定义比较两个对象的逻辑

她:哦,好的。你知道值传递和引用传递的区别吗

我:值传递传递的是数值,而地址……额……Java中方法形参是按值传递的,如果是基本变量,那方法无论做什么也不会改变该变量的值,而如果是引用变量,那可以根据地址改变其中的属性。(其实应该这么说,如果是基本变量,形参接收的只是变量数值的一个副本,而如果是引用变量则接收的是一个对象的地址,无法通过方法的形参改变原变量的值,但如果原变量是引用类型的话,可以改变其指向的对象的成员变量)

她:哦,好的。你知道String、StringBuffer、StringBuilder之间的区别吗?

我:String具有不可变特性,一经创建就不可改变,在其上做的任何操作只可能产生新的String,而StringBuffer中的字符串则是可以通过其API来改变的,StringBuilder和StringBuffer的区别就是StringBuilder是线程安全的,也就是说在多线程、高并发的场景下建议使用StringBuilder,单线程下两者有相同的API,没有区别(完了……完全说反了StringBuffer才是线程安全的)

她:哦,好的。你知道GC吗,什么样的对象可以被回收?

我:我知道的有GC算法有标记清除、根可达性……就是从根对象能否到达此对象……哦,不对……什么样的对象可以被回收……嗯……不被栈中变量引用的对象被认为是可以回收的。

她:哦,好的。你说的根可达性是什么

我:我之前看过根可达性是一种GC策略,然后被栈中变量引用的对象会以静态实例作为头结点形成一条引用链,如果运行过程中,你将某引用变量置为null而使该变量引用的实例脱离了这条链,那么该实例是无法从头结点沿引用链到达的,是可以被回收的……

她:哦,好的。你知道Java运行时,内存分为哪几块吗?

我:额……运行时首先遇到没有加载的类,会将其字节码加载到永久方法区,静态实例也会存放于永久方法区,栈一般存放引用变量,而所有创建的对象都会放在堆内存中。堆内存是共享内存,也就是所有线程都可以共享的。

她:你知道线程之间如何通信吗

我:据我所知,线程之间通信有显示和隐式两种方式。显示的是指,如果某线程将其本地内存(这是一个抽象概念,代表的是线程的缓存、缓冲区)中修改过的数据刷新到主内存,那么根据缓存一致性原则,其它线程如果之前读过这个变量到自己的本地内存,这些线程会因为主内存变量的更新而重新读取再行操作;而隐式的是指,线程之间使用wait和notify通信。

她:哦,好的。线程有哪几种状态?

我:线程一经new创建就进入新建状态,如果调用其start方法则会进入就绪状态,这时线程会争CPU分配的时间片,如果争到了即获得CPU执行权,进入执行状态,这时可能会中断、阻塞、等待,等待的话会进入等待状态等待其他线程将其唤醒,否则中断的话会异常结束或者正常执行完也是进入结束状态,就是这五种状态吧

她:你知道什么是线程安全吗?

我:我了解的线程安全问题,就是变量的可见性问题,就是说CPU执行某个线程时,一般不会直接操作主内存,而会将主内存中的数据读到缓存中,对缓存的数据做读改写之后再更新到内存,而每个线程都有每个线程的缓存,并且一个线程的缓存只有它自己知道,对其他线程是不可见的,因此在一个线程对内存的变量做读改写,将结果保存到写缓冲区准备更新到主内存之前,其他线程是不知道这一改动的,其他线程可能还在访问主内存中原先的变量

她:哦,好的。对于线程A和线程B,要求两个线程交替输出ABABAB,你有几种实现方法

我:第一种,使用一个布尔变量flag,并用volatile修饰,然后A、B线程判断该变量的值,如果是true就打印A否则打印B,并且在打印之后对该变量取反!flag(其实我自己都不知道自己在说什么……欠缺思考);第二种是使用wait/notify的方式,线程A打印A后就通知线程B打印B,然后线程A进入等待,线程B被唤醒后打印B然后通知线程A打印A,自己进入等待

她:哦,好的。你知道哪些锁?

我:不就synchronized一种锁吗?(我好像曲解了她的意思)然后synchronized对应有三种锁状态:偏向锁、轻量级锁、重量级锁

她:哦,好的。你知道乐观锁吗

我:乐观锁……值得是CAS吗?CAS就是为了解决获得锁和释放锁带来的性能消耗,是一种无锁更新操作。思路是更新一个数据之前,首先记录以下该数据当前的值,然后根据逻辑做改写操作之后要更新它时比较一下它还是不是原来读到的值,如果是则更新,否则重新记一下该值,再基于该值做改写,最后更新的时候再比较一下是不是原先读到的值。这个过程称为自旋,自旋的缺点是消耗CPU资源。

她:哦,好的。设计模式你都了解哪些?

我:额……设计模式,我只记得常用的几个……比如单例模式、抽象工厂、装饰者模式、观察者模式、建造者模式……

她:哦,好的。说一下你说的装饰者模式

我:(还好没问我建造者模式,我自己都不知道),装饰者模式的目的就是增强某个特定的功能,比如IO读写流中的XXBuffer类就是运用了此类设计模式增强了读写的功能,提高了读写效率。我自己在项目中也有使用过,记得当时是增强了HttpServletResponse的输出功能,但具体增强了什么我也忘了。

她:哦,好的。那装饰者模式有什么缺点

我:它的缺点就是只能在原方法的前后做一个增强,但不能进行环绕增强,比如如果原方法跑出了异常,增强方法也会跟着跑出异常,无法做到捕获做进一步的处理

她:哦,好的。那使用装饰者增强的类会有什么影响吗?跟使用原类对比

我:我记得一句口诀是:是你还有你,一切拜托你。就是增强类首先要继承被增强类,然后,增强类中还要有一个被增强类的实例,增强类的所有API都和原类相同,只不过对某个特定的方法做了增强,在调用原方法的前后加上了业务需要的额外功能。

她:哦,好的。synchronize可以重入吗

我:是可以重入的。比如一个线程在进入一个同步代码块获取到一个对象的锁之后,又遇到一个同步代码块,获取了另一个对象的锁。(我觉得她应该是想问,一个线程持有一个对象的锁之后,再遇到一个需要该锁的同步代码块,能否再进入,是可以的)

她:哦,好的。你知道哪些排序算法

我:数组的话,有冒泡、选择、插入、快排、归并、桶排序、计数排序……

她:那你说一下快排

我:经典快排就是随机选出数组中的一个数并和末尾元素交换位置,然后将数组中的元素以该数为比较标准分为大于该数的区域和小于等于该数的区域,然后这是一个递归过程,对大于区域、小于等于区域两部分递归该过程。

她:你说了经典快排,还有其他快排吗

我:还有由荷兰国旗问题改进的快排,就是经典快排一次只能解决一个数,就是那个被随机选择的数,而荷兰国旗问题是将数组分为大于区域、等于区域、小于区域三个区域,一次操作解决的是等于区域的所有数,效率比经典快排略高

她:哦,好的。你知道跳表的原理吗

我:额……我前几天还手写过,就是插入一条数据之前首先生成该数据对应的层数,这个层数是由抛硬币第一次抛出正面朝上时一共抛了多少次决定的,然后结构是由一个哈希表存储所有进入的记录,另外一个链表,每个节点存放一条记录,每个节点又有很多结点代表该记录的层数。由于查找数据时总是从最高层结点向右或向下滑动来查找的,而结点每上一层基本上都会少1/2的记录,因此查找效率可以和AVL数、红黑树、SizeBalance树媲美。

她:那你说跳表和AVL树、红黑树、SBT的查找时间复杂度都是log(2,N),那跳表和他们的区别是什么呢

我:就是跳表是其中最容易实现的一个。在工程中,你可以自己根据业务需求定制跳表,而AVL树、红黑树等实现较为复杂,一般都是拿过来直接使用,因为只知道原理,手写很难

她:哦,好的。你知道Java中有些集合?有看过源码吗,知道是怎么实现的吗?

我:我知道的有ArrayList、LinkedList、HashMap、TreeMap还有优先级队列PriorityQueue(我怎么忘了说Stack、HashSet呢)。源码的话倒是没看多,但是学了数据结构,知道ArrayList是具有数组特性的链表、LinkedList是双向链表也可以当做双端队列来使用、TreeMap是红黑树结构

她:哦,好的。其中那几个集合是线程安全的?

我:HashMap不是线程安全的,多线程场景下可能会导致其中形成环形链表而进入死循环,应该使用ConcurrentHashMap

她:你知道堆排序吗

我:额……这个我之前也手写过,就是将一个数组以下标对应的形式当成一棵二叉树来看,然后大根堆就是对于任意一棵子树,根节点最大。

她:IO和NIO了解多少?

我:额……IO和NIO方面我比较欠缺

她:哦,好的。了解几种数据库?

我:目前只用过Mysql,Oracle还没学,然后NoSql用过Redis,MongDB有过入门

她:MySql建表三种范式知道吗

我:不太清楚

她:MySql索引有了解吗

我:额……不太清楚,比较薄弱

她:Spring用过吗?好处是什么?

我:我现在的项目一般都会用到Spring,Spring的好处就是颠覆了Java传统的开发方式,我们在使用一个类之前都要手动new一个该类的实例,这样不太好,因为每次new都会消耗内存而我们的应用程序可能就只需要一个该类的实例而不是每次用都要new。Spring就很好的解决了此问题,帮助我们管理了bean,并且单例、多例可自行配置。

她:那单例和多例怎么配置?

我:额……配置bean时默认就是单例,singleton,如果要设置多例的话,好像是prototype

她:配置一个bean时,如何指定引用另一个bean

我:通过bean的id或name

她:Spring的注解有哪些?

我:额……(好久没写项目,感觉都忘了),勉强说了个GetMapping、PostMapping、Service、Repository,你说Spring吗,额……Autowire(其实还有Reference、Resource,Transaction)

她:AOP有了解吗?

我:有过一些了解……就是传统的增强类的方式一般是通过继承,是自顶向下的,但是这种方式有很多局限性,而AOP是通过***模式在不改变原有代码的基础之上横向的穿插新功能对原有方法进行增强。Spring的事务就是使用了AOP,日志打印好像也可以用AOP

她:反射知道多少?

我:Java的是通过reflect包实现的(应该是reflex啊)。我在项目中用到的反射一般都跟泛型有关,比如在DAO层,需要抽出一个BaseDAO来动态生成基本的CRUD操作时会用到,主要是动态的获取类的一些字段和方法。

她:通过泛反射得到类的私有字段吗?

我:……好像可以吧,但是跟非私有字段不同,好像要先调用setAccessibale更改一下访问权限

她:Linux了解多少?

我:一般就是服务端常用软件的安装、字节码的编译、环境的配置等。

她:linux查看文件的命令有哪些

我:vi、vim、cat、tail,就说得出这么多了……

她:项目用过maven吗

我:一般都会用maven的,依赖管理比较方便

她:Maven的生命周期有哪些

我:clean、install、package,常用的就这些

她:Git用过吗,常用命令有哪些

我:add、commit、checkout、remote……用得太少了

她:了解过持续集成吗

我:直到Jekins可以做,但没学过

她:数据库事务知道吗?

我:就是开启事务之后的提交不会立刻生效,在提交事务时才会生效

她:有哪些隔离级别

我:好像有三四中,这个记不太清了

她:开启事务之后可能会让数据变乱吗

我:不会吧,要么都失败、要么都成功,

她:你有哪些项目经历

我:做过一个PPT展示和付费下载的网站,做过一个电商网站

她:你负责哪些模块的开发?

我:商家后台、运营商后台、商品搜索模块、购物车模块

她:你有什么想问我的吗?

我:额……这其实是我第一次面试,你有什么建议吗

接近一个小时的面试,说实话还是有些紧张的,有些问题支支吾吾、答非所问、表达不清,其实很多问题可以表现的更好。

#趣链科技##实习##面经##Java工程师#
全部评论
好认真啊
点赞 回复
分享
发布于 2018-12-17 16:02
这么多?实习吗
点赞 回复
分享
发布于 2018-12-17 17:53
饿了么
校招火热招聘中
官网直投
想问问你是咋记下这么多的。。。
点赞 回复
分享
发布于 2018-12-17 23:57
趣链我朋友电面通过之后过去总部谈了薪资,但是后面打电话说人招满了,现在又来招人,不是很懂这种操作😞
点赞 回复
分享
发布于 2018-12-18 00:49
现在实习生都这么恐怖了吗
点赞 回复
分享
发布于 2018-12-28 07:46
问的不深,但是很广啊
点赞 回复
分享
发布于 2018-12-28 08:46

相关推荐

9 68 评论
分享
牛客网
牛客企业服务