阿里巴巴java工程师电话面试题(付答案)

一、String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的?

答:   

1、String是字符串常量,StringBuffer和StringBuilder都是字符串变量。后两者的字符内容可变,而前者创建后内容不可变。

2、String不可变是因为在JDK中String类被声明为一个final类。

3、StringBuffer是线程安全的,而StringBuilder是非线程安全的。

ps:线程安全会带来额外的系统开销,所以StringBuilder的效率比StringBuffer高。


二、Vector,ArrayList, LinkedList的区别是什么?

答:   

1、Vector、ArrayList都是以类似数组的形式存储在内存中,LinkedList则以链表的形式进行存储。

2、Vector线程同步,ArrayList、LinkedList线程不同步。

3、LinkedList适合指定位置插入、删除操作,不适合查找;ArrayList、Vector适合查找,不适合指定位置的插入、删除操作。

4、ArrayList在元素填满容器时会自动扩充容器大小的50%,而Vector则是100%,因此ArrayList更节省空间。

ps:List中的元素有序、允许有重复的元素,Set中的元素无序、不允许有重复元素。


三、HashTable, HashMap,TreeMap区别?

答:   

1、HashTable线程同步,HashMap非线程同步。

2、HashTable不允许<键,值>有空值,HashMap允许<键,值>有空值。

3、HashTable使用Enumeration,HashMap使用Iterator。

4、HashTable中hash数组的默认大小是11,增加方式的old*2+1,HashMap中hash数组的默认大小是16,增长方式一定是2的指数倍。

5、TreeMap能够把它保存的记录根据键排序,默认是按升序排序。


四、Tomcat,Apache,JBoss的区别?

答:   

1、Apache是Http服务器,Tomcat是web服务器,JBoss是应用服务器。

2、Apache解析静态的html文件;Tomcat可解析jsp动态页面、也可充当servlet容器。


五、GET,POST区别?

答:

1、Get是从服务器端获取数据,Post则是向服务器端发送数据。Get获取html等静态资源时,如果静态资源没有改变,则返回304状态码(not modify),使用浏览器端的缓存

2、在客户端,Get方式通过URL提交数据,在URL地址栏可以看到请求消息,该消息被编码过;Post数据则是放在Html header内提交。

3、对于Get方式,服务器端用Request.QueryString获取变量的值;对用Post方式,服务器端用Request.getParameter获取提交的数据值。

4、Get方式提交的数据最多1024字节(和浏览器有关,可以更大),而Post则没有限制。

5、Get方式提交的参数及参数值会在地址栏显示,不安全,而Post不会,比较安全。


六、Session, Cookie区别

答:  

1、Session由应用服务器维护的一个服务器端的存储空间;Cookie是客户端的存储空间,由浏览器维护。

2、用户可以通过浏览器设置决定是否保存Cookie,而不能决定是否保存Session,因为Session是由服务器端维护的。

3、Session中保存的是对象,Cookie中保存的是字符串。

4、Session、Cookie都有失效时间,过期后会自动删除,减少系统开销。

ps:关于Session, Cookie的详细介绍,请查看本公众号的另一篇文章(关注《JAVA之庖丁解牛》,回复“vs”)



七、Servlet的生命周期

答:   

大致分为4部:Servlet类加载-->实例化-->服务-->销毁


八、HTTP 报文包含内容

答:   

主要包含四部分:

1、request line

2、header line

3、blank line

4、request body


九、Statement与PreparedStatement的区别

答:  

1、PreparedStatement支持动态设置参数,Statement不支持。

2、PreparedStatement可避免如类似 单引号 的编码麻烦,Statement不可以。

3、PreparedStatement支持预编译,Statement不支持。

4、在sql语句出错时PreparedStatement不易检查,而Statement则更便于查错。

5、PreparedStatement可防止Sql注入,更加安全,而Statement不行。


十、什么是SQL注入,如何防止SQL注入

 通过sql语句的拼接达到无参数查询数据库数据目的的方法。

 如将要执行的sql语句为 select * from table where name = "+appName+",利用appName参数值的输入,来生成恶意的sql语句,如将['or'1'='1']  传入可在数据库中执行。

 因此可以采用PrepareStatement来避免Sql注入,在服务器端接收参数数据后,进行验证,此时PrepareStatement会自动检测,而Statement不行,需要手工检测。

 

十一、sendRedirect, foward区别

答:

  foward是服务器端控制页面转向,在客户端的浏览器地址中不会显示转向后的地址;

  sendRedirect则是完全的跳转,浏览器中会显示跳转的地址并重新发送请求链接。


ps:forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后再将这些内容返回给浏览器,浏览器根本不知道服务器发送的这些内容是从哪来的,所以地址栏还是原来的地址。

    redirect是服务器端根据逻辑,发送一个状态码(307),告诉浏览器重新去请求的那个地址,浏览器会用刚才的所有参数重新发送新的请求。

十二、关于Java内存模型,一个对象(两个属性,四个方法)实例化100次,现在内存中的存储状态,几个对象,几个属性,几个方法。

答:   

由于JAVA中new出来的对象都是放在堆中,所以如果要实例化100次,将在堆中产生100个对象,一般对象与其中的属性、方法都属于一个整体,

但如果属性和方法是静态的(使用static关键字声明),那么属于类的属性和方法永远只在内存中存在一份。


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

答:

在运行状态中,动态获取类信息或者动态调用类对象方法的功能称为java的反射机制。

反射的作用:

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

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


十四、谈谈Hibernate与Ibatis的区别,哪个性能会更高一些

答:   

1、Hibernate偏向于对象的操作达到数据库相关操作的目的;而ibatis更偏向于sql语句的优化。

2、Hibernate的使用的查询语句是自己的hql,而ibatis则是标准的sql语句。

3、Hibernate相对复杂,不易学习;ibatis类似sql语句,简单易学。


性能方面:

1、如果系统数据处理量巨大,性能要求极为苛刻时,往往需要人工编写高性能的sql语句或存错过程,此时ibatis具有更好的可控性,因此性能优于Hibernate。

2、同样的需求下,由于hibernate可以自动生成hql语句,而ibatis需要手动写sql语句,此时采用Hibernate的效率高于ibatis。

 

 十五、对Spring的理解,项目中都用什么?怎么用的?对IOC、和AOP的理解及实现原理

答:   

spring是一个开源框架,处于MVC模式中的控制层,它能应对需求快速的变化,其主要原因它有一种面向切面编程(AOP)的优势,其次它提升了系统性能,因为通过依赖倒置机制(IOC),

系统中用到的对象不是在系统加载时就全部实例化,而是在调用到这个类时才会实例化该类的对象,从而提升了系统性能。这两个优秀的性能使得Spring受到许多J2EE公司的青睐,

如阿里里中使用最多的也是Spring相关技术。


Spring的优点:

1、降低了组件之间的耦合性,实现了软件各层之间的解耦。

2、可以使用容易提供的众多服务,如事务管理,消息服务,日志记录等。

3、容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。


Spring中AOP技术是设计模式中的动态代理模式。只需实现jdk提供的动态代理接口InvocationHandler,所有被代理对象的方法都由InvocationHandler接管实际的处理任务。

Spring中IOC则利用了Java强大的反射机制来实现。所谓依赖注入即组件之间的依赖关系由容器在运行期决定。其中依赖注入的方法有两种,通过构造函数注入,通过set方法进行注入。

 

十六、线程同步,并发操作怎么控制 

答:   

Java中可在方法名前加关键字syschronized来处理当有多个线程同时访问共享资源时候的问题。syschronized相当于一把锁,当有申请者申请该

资源时,如果该资源没有被占用,那么将资源交付给这个申请者使用,在此期间,其他申请者只能申请而不能使用该资源,当该资源被使用完成后将释放该资源上的锁,

其他申请者可申请使用。


并发控制主要是为了多线程操作时带来的资源读写问题。如果不加以控制可能会出现死锁,读脏数据、不可重复读、丢失更新等异常。

并发操作可以通过加锁的方式进行控制,锁又可分为乐观锁和悲观锁。


悲观锁:

并发模式假定系统中存在足够多的数据修改操作,以致于任何确定的读操作都可能会受到由个别的用户所制造的数据修改的影响。也就是说悲观锁假定冲突总会发生,

通过独占正在被读取的数据来避免冲突。但是独占数据会导致其他进程无法修改该数据,进而产生阻塞,读数据和写数据会相互阻塞。


乐观锁:

假定系统的数据修改只会产生非常少的冲突,也就是说任何进程都不大可能修改别的进程正在访问的数据。乐观并发模式下,读数据和写数据之间不会发生冲突,

只有写数据与写数据之间会发生冲突。即读数据不会产生阻塞,只有写数据才会产生阻塞 


十七、 DB中索引原理,种类,使用索引的好处和问题是什么? 

答:    

经常需要修改的表不益建立索引,因为数据库对索引进行维护需要额外的开销。对经常需要查询的大数据表需要建立索引,这样会增加查询的效率。

索引的种类:B*Tree、反向索引、降序索引、位图索引、函数索引


ps:更详细内容请查看本公众号的文章,(关注《JAVA之庖丁解牛》,回复“mysql”)


十八、JVM垃圾回收算法、垃圾回收类型、垃圾收集器

回收算法:

1、引用计数(Reference Counting)

2、复制(Copying) 

3、标记清除(Mark-Sweep) 

4、标记整理(Mark-Compact)

5、增量收集(Incremental Collecting) 

6、分代收集(Generational Collecting)

回收类型:

    1、Scavenge GC 

2、Full GC

收集器:

    1:串行收集器 SerialGC

    2:并行收集器 ParallelGC

    3:并发收集器 ConcMarkSweepGC

ps:详细介绍请参考http://chenchendefeng.iteye.com/blog/455883


十九、自定义一个包,里面有class文件,如果放在java jdk里面,该包的class文件会被加载吗

答:需要看存放的位置,如果存放在jre/lib/ext/下,会被加载,否则不会加载,如果需要加载,需要自定义类加载器


ps:类加载器加载原理采用父亲委托方式进行类的加载,一个类的加载器,有且仅有一个父类。层次如下,

   bootstrap(c++实现)<--extclassLoader(java实现)<--appClassLoader(java实现)<--myClassLoader(java自定义类加载器)

   1、凡是java代码,都需要一个类加载器加载,所以最根的boostrap不是用java实现的。boostrap负责加载jre/lib/rt.jar的类

   2:extclassLoader负责加载jre/lib/ext/下的类。第十九问题的答案出于此

   3:appClassLoader负责加载项目中classpath的类

   4:myClassLoader 负责加载项目中非classpath的类。不建议这么写,建议采用接口调用方式

   

   

类加载器的委托机制:

当Java虚拟机要加载第一个类的时候,到底派出哪个类加载器去加载呢?

(1). 首先当前线程的类加载器去加载线程中的第一个类

(2). 如果类A中引用了类B,Java虚拟机将使用加载类A的类加载器来加载类B

(3). 还可以直接调用ClassLoader.loadClass(String className)方法来指定某个类加载器去加载某个类

每个类加载器加载类时,又先委托给其上级类加载器当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则会抛出ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild()方法。例如:如上图所示: MyClassLoader->AppClassLoader->Ext->ClassLoader->BootStrap.自定定义的MyClassLoader1首先会先委托给AppClassLoader,AppClassLoader会委托给ExtClassLoader,ExtClassLoader会委托给BootStrap,这时候BootStrap就去加载,如果加载成功,就结束了。如果加载失败,就交给ExtClassLoader去加载,如果ExtClassLoader加载成功了,就结束了,如果加载失败就交给AppClassLoader加载,如果加载成功,就结束了,如果加载失败,就交给自定义的MyClassLoader1类加载器加载,如果加载失败,就报ClassNotFoundException异常,结束。