阿里笔试面试题解析,java方向(暑期充点电必看!)

-回复 -浏览
楼主 2019-01-10 16:09:36
举报 只看此人 收藏本贴 楼主

      最近这几周有很多互联网公司开展了秋招的预演——内推活动,这让大家提前踏上求职之路,根据自己的求职经验和大牛的建议,给求职路上的菜鸟几点中肯的意见:

       1.万事要有自己的计划,和对自己的合理评估,没有那么多讨巧的事情,所以求职之前还要合理的剖析自己,漂亮的简历、学长学姐的内推可能刚刚是万里长征的第一步,最主要看的还是自己的能力,打铁还要功夫硬;

        2.说句泼冷水的话,不是所有人都适合大公司,锻炼和成长是需要在实战中磨练的,增加一些实战实习经历、多研究一些产品或算法等才是你求职路上最有力的支撑!

PS:由于下周一周小编要去外地,所以7月31日到——8月6日将没有微信的推送,8月7日起,小编将和大家一起备战秋招!

Volatile

Volatile的特征:

A、禁止指令重排(有例外) 
B、可见性

Volatile的内存语义:

当写一个volatile变量时,JMM会把线程对应的本地内存中的共享变量值刷新到主内存。

当读一个volatile变量时,JMM会把线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量。

Volatile的重排序

1、当第二个操作为volatile写操做时,不管第一个操作是什么(普通读写或者volatile读写),都不能进行重排序。这个规则确保volatile写之前的所有操作都不会被重排序到volatile之后;

2、当第一个操作为volatile读操作时,不管第二个操作是什么,都不能进行重排序。这个规则确保volatile读之后的所有操作都不会被重排序到volatile之前;

3、当第一个操作是volatile写操作时,第二个操作是volatile读操作,不能进行重排序。

这个规则和前面两个规则一起构成了:两个volatile变量操作不能够进行重排序;

除以上三种情况以外可以进行重排序。

比如:

1、第一个操作是普通变量读/写,第二个是volatile变量的读; 
2、第一个操作是volatile变量的写,第二个是普通变量的读/写;

内存屏障/内存栅栏

内存屏障(Memory Barrier,或有时叫做内存栅栏,Memory Fence)是一种CPU指令,用于控制特定条件下的重排序和内存可见性问题。Java编译器也会根据内存屏障的规则禁止重排序。(也就是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术。)

内存屏障可以被分为以下几种类型:

LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。

StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。

LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。

StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。

在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。

内存屏障阻碍了CPU采用优化技术来降低内存操作延迟,必须考虑因此带来的性能损失。为了达到最佳性能,最好是把要解决的问题模块化,这样处理器可以按单元执行任务,然后在任务单元的边界放上所有需要的内存屏障。采用这个方法可以让处理器不受限的执行一个任务单元。合理的内存屏障组合还有一个好处是:缓冲区在第一次被刷后开销会减少,因为再填充改缓冲区不需要额外工作了。

happens-before原则

Java是如何实现跨平台的?

跨平台是怎样实现的呢?这就要谈及Java虚拟机(Java Virtual Machine,简称 JVM)。

JVM也是一个软件,不同的平台有不同的版本。我们编写的Java源码,编译后会生成一种 .class 文件,称为字节码文件。Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码然后运行。也就是说,只要在不同平台上安装对应的JVM,就可以运行字节码文件,运行我们编写的Java程序。

而这个过程中,我们编写的Java程序没有做任何改变,仅仅是通过JVM这一”中间层“,就能在不同平台上运行,真正实现了”一次编译,到处运行“的目的。

JVM是一个”桥梁“,是一个”中间件“,是实现跨平台的关键,Java代码首先被编译成字节码文件,再由JVM将字节码文件翻译成机器语言,从而达到运行Java程序的目的。

注意:编译的结果不是生成机器码,而是生成字节码,字节码不能直接运行,必须通过JVM翻译成机器码才能运行。不同平台下编译生成的字节码是一样的,但是由JVM翻译成的机器码却不一样。

所以,运行Java程序必须有JVM的支持,因为编译的结果不是机器码,必须要经过JVM的再次翻译才能执行。即使你将Java程序打包成可执行文件(例如 .exe),仍然需要JVM的支持。

注意:跨平台的是Java程序,不是JVM。JVM是用C/C++开发的,是编译后的机器码,不能跨平台,不同平台下需要安装不同版本的JVM。

Java 线程有哪些状态

这些状态之间是如何转化的?

1.新建(new):新创建了一个线程对象。

2.可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

3.运行(running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。

4.阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:

(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。

(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。

(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

List接口、Set接口和Map接口的区别

友情链接:List接口、Set接口和Map接口的区别:

http://blog.csdn.net/zcg_java/article/details/43232251

Cookie和Session的区别?

友情链接:Cookies 和 Session的区别

http://blog.csdn.net/axin66ok/article/details/6175522

Java中的equals和hashCode方法详解

友情链接:Java提高篇——equals()与hashCode()方法详解

http://www.cnblogs.com/Qian123/p/5703507.html

Java中CAS算法

友情链接:乐观的并发策略——基于CAS的自旋

http://www.kancloud.cn/seaboat/java-concurrent/117870

TimSort原理

友情链接:TimSort原理

http://baike.baidu.com/link?url=4tXLGfO_VjPOOmWTZxhiGg5EyojbWvysoIPtbxqtyEpuwoVOtl43_15ds0XYHTPrQlkucF-yr_H5XztSB9KTB2bXluoWjrCgY22SbikKiTW

comparable与comparator的区别?

友情链接:Comparable和Comparator的区别

http://www.cnblogs.com/szlbm/p/5504634.html

手写单例模式(线程安全)

友情链接:快速理解Java中的五种单例模式

http://www.cnblogs.com/hupp/p/4487521.html

Java线程间的通信方式?

友情链接:Java 多线程(七) 线程间的通信——wait及notify方法 

http://www.cnblogs.com/mengdd/archive/2013/02/20/2917956.html

友情链接:Java线程间的通信方式详解

http://www.jb51.net/article/84213.htm

Java8的内存分代改进

友情链接:Java7、Java8的堆内存有啥变化?

http://blog.csdn.net/chlu113/article/details/51890469

对Java内存模型的理解以及其在并发当中的作用?

友情链接:对Java内存模型的理解以及其在并发当中的作用?

http://www.cnblogs.com/_popc/p/6096517.html

Arrays和Collections 对于sort的不同实现原理?

1、Arrays.sort() 
该算法是一个经过调优的快速排序,此算法在很多数据集上提供N*log(N)的性能,这导致其他快速排序会降低二次型性能。

2、Collections.sort() 
该算法是一个经过修改的合并排序算法(其中,如果低子列表中的最高元素效益高子列表中的最低元素,则忽略合并)。此算法可提供保证的N*log(N)的性能,此实现将指定列表转储到一个数组中,然后再对数组进行排序,在重置数组中相应位置处每个元素的列表上进行迭代。这避免了由于试图原地对链接列表进行排序而产生的n2log(n)性能。

Java中object常用方法

1、clone() 

2、equals() 
3、finalize() 
4、getclass() 
5、hashcode() 
6、notify() 
7、notifyAll() 
8、toString()

对于Java中多态的理解

所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

Java实现多态有三个必要条件:继承、重写、父类引用指向子类对象。

继承:在多态中必须存在有继承关系的子类和父类。

重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

父类引用指向子类对象:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

多态的作用:消除类型之间的耦合关系。

Session机制?

友情链接 :Session机制详解

http://justsee.iteye.com/blog/1570652

Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?

友情链接 : Java序列化与反序列化

http://blog.csdn.net/wangloveall/article/details/7992448/

spring AOP 实现原理?

友情链接 :Spring AOP 实现原理

http://blog.csdn.net/moreevan/article/details/11977115/

Servlet 工作原理?

友情链接 :Servlet 工作原理解析

http://www.ibm.com/developerworks/cn/java/j-lo-servlet/

java NIO和IO的区别?

友情链接 :Java NIO和IO的区别

http://www.jb51.net/article/50621.htm

Java中堆内存和栈内存区别?

友情链接 :Java中堆内存和栈内存详解

http://www.cnblogs.com/whgw/archive/2011/09/29/2194997.html

反射讲一讲,主要是概念,都在哪需要反射机制,反射的性能,如何优化?

反射机制的定义:

是在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象方法的功能称为java的反射机制。

反射的作用:

1、动态地创建类的实例,将类绑定到现有的对象中,或从现有的对象中获取类型。

2、应用程序需要在运行时从某个特定的程序集中载入一个特定的类。

如何保证RESTful API安全性 ?

友情链接: 如何设计好的RESTful API之安全性

http://blog.csdn.net/ywk253100/article/details/25654101

如何预防MySQL注入?

友情链接:MySQL 及 SQL 注入与防范方法

http://www.jb51.net/article/87948.htm

以上内容转自:作者:HuangQinJian博客,原题目:历年阿里面试题汇总(2017年不断更新中)

阿里巴巴2017实习生

笔试题+JAVA工程师能力评估部分题目

1.由权值分别为1、12、13、4、8的叶子节点生成一颗哈夫曼树,它的带权路径长度为()

2.进程间的通信方式

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 

# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 

# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。 

# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。 

# 套接( socket ) : 套解口也是一种字进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

3.同一个进程中的线程不共享的部分是()

每个线程都有自己独立的线程上下文,包括线程ID、栈、栈指针、程序计数器、条件码和通用目的寄存器值。每个线程和其他线程一起共享进程上下文的剩余部分:用户虚拟地址空间(代码,堆,打开文件的集合)。

       char :1个字节

       char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)

      short int : 2个字节

      int: 4个字节

      unsigned int : 4个字节

      float: 4个字节

      double: 8个字节

      long: 4个字节

      long long: 8个字节

      unsigned long: 4个字节

  64位编译器:

      char :1个字节

      char*(即指针变量): 8个字节

      short int : 2个字节

     int: 4个字节

      unsigned int : 4个字节

      float: 4个字节

      double: 8个字节

      long: 8个字节

      long long: 8个字节

      unsigned long: 8个字节

JAVA工程师能力评估部分题目

1.SPRING的事务传播特性

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 

PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 

PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 

PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 

PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 

PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。 

2.Servlet 与 CGI 的比较

和CGI程序一样,Servlet可以响应用户的指令(提交一个FORM等等),也可以象CGI程序一样,收集用户表单的信息并给予动态反馈(简单的注册信息录入和检查错误)。

然而,Servlet的机制并不仅仅是这样简单的与用户表单进行交互。传统技术中,动态的网页建立和显示都是通过CGI来实现的,但是,有了Servlet,您可以大胆的放弃所有CGI(perl?php?甚至asp!),利用Servlet代替CGI,进行程序编写。 

对比一:当用户浏览器发出一个Http/CGI的请求,或者说 调用一个CGI程序的时候,服务器端就要新启用一个进程 (而且是每次都要调用),调用CGI程序越多(特别是访问量高的时候),就要消耗系统越多的处理时间,只剩下越来越少的系统资源,对于用户来说,只能是漫长的等待服务器端的返回页面了,这对于电子商务激烈发展的今天来说,不能不说是一种技术上的遗憾。

而Servlet充分发挥了服务器端的资源并高效的利用。每次调用Servlet时并不是新启用一个进程 ,而是在一个Web服务器的进程敏感词享和分离线程,而线程最大的好处在于可以共享一个数据源,使系统资源被有效利用。

 对比二:传统的CGI程序,不具备平台无关性特征,系统环境发生变化,CGI程序就要瘫痪,而Servlet具备Java的平台无关性,在系统开发过程中保持了系统的可扩展性、高效性。 

对比三:传统技术中,一般大都为二层的系统架构,即Web服务器+数据库服务器,导致网站访问量大的时候,无法克服CGI程序与数据库建立连接时速度慢的瓶颈,从而死机、数据库死锁现象频繁发生。而我们的Servlet有连接池的概念,它可以利用多线程的优点,在系统缓存中事先建立好若干与数据库的连接,到时候若想和数据库打交道可以随时跟系统"要"一个连接即可,反应速度可想而知

3.Servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。

(1)加载:容器通过类加载器使用servlet类对应的文件加载servlet

(2)创建:通过调用servlet构造函数创建一个servlet对象

(3)初始化:调用init方法初始化

(4)处理客户请求:每当有一个客户请求,容器会创建一个线程来处理客户请求

(5)卸载:调用destroy方法让servlet自己释放其占用的资源

4.sleep和wait

sleep是线程类(Thread)的方法,执行此方法会导致当前此线程暂停指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。

wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法或notifyAll后本线程才获得对象锁进入运行状态

转自:bo602505401的博客:

阿里巴巴2017实习生笔试题+JAVA工程师能力评估部分题目

我要推荐
转发到