[关闭]
@HUST-SuWB 2016-04-12T07:45:31.000000Z 字数 10834 阅读 348

校招求职的试题整理

其他

  1. Java对象的初始化过程?
    对于对象创建的过程,假设有个名为Dog的类,则:
    即使没有使用static,构造器实际上也是静态方法,因此当首次创建类型为Dog的对象时,或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件;
    然后载入Dog.class(这会创建一个class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在class对象首次加载时进行一次;
    当用new Dog()创建对象时,首先在堆上为Dog对象分配足够的存储空间;
    这块存储空间会被清零,这就自动将Dog对象中所有基本类型都设置成了默认值,而引用被设置为null;
    执行所有出现于字段定义处的初始化工作;
    执行构造器。
    (转自Java编程思想)
    而对于有继承的情况是:
    当首次创建型为Mouse4j的对象时,Java解释器查找类路径,定位Mouse4j.class文件。Java解释器会根据Mouse4j.class定位其基类Mouse.class、再根据Mouse.class定位到基类Animal.class文件,有关静态初始化的动作从基类到子类依次执行。当你用new Mouse4j()创建对象的时候,首先将在堆上为Mouse4j对象(包括其基类Mouse和Animal中的域)分配足够的存储空间。这块存储空间会被清零,这就自动地将Mouse4j中的所有基本类型数据(包括其基类Mouse和Animal中的)设置成了默认值(对数字来说就是0,对布尔型和字符型也相同),而引用(包括其基类Mouse和Animal中的)则被置成了null。
    在为所创建对象的存储空间清零后,找到继承链中最上层的基类,执行a、b两步:
    a.执行其出现在域定义处的初始化动作
    b.然后再执行其构造器
    然后从基类到子类依次执行这两步操作。
  2. final的关键字有什么作用?
    final数据:final用于基本类型时,作用是使数值恒定不变;final用于对象引用时,作用是使引用恒定不变,但是引用的对象而言,其对象变身是可以修改的,这一限制同样适用于数组,因为数组也是对象
    final方法:final方法主要用于禁止子类对父类的覆盖。因此,类中所有的private方法都隐中式的指定为final,因为它们都不会被继承,更不会被覆盖了
    final类:final类表明你不打算继承该类,也不打算允许别人继承
  3. Java的内存模型,一个堆,一个栈,你有关注过么?
    Java虚拟机栈(Java Virtual Machine Stacks)
    Java每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。其中局部变量表存放了编译器可知的各种基本数据类型、对象引用(reference类型,它不等同于对象本身,可能是指向对象起始地址的引用指针,也可能指向一个代表对象的句柄)returnAddress类型。
    如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。
    本地方法栈(Native Method Stack)
    与虚拟机栈的作用是类似的,只不过虚拟机栈为虚拟机执行Java方法,而本地方法栈为虚拟机使用到的Native方法服务。会抛出StackOverflowError和OutOfMemoryError异常。
    Java堆(Java Heap)
    被所有线程线程共享的一块内存区域,在虚拟机创建时创建:几乎所有的对象实例和数组都要在堆上分配。堆是垃圾回收的主要区域,从内存回收的角度,堆还可以细分为:新生代和老年代,新生代还可以分为Eden空间、From Survior空间、To surviot空间。从内存分配的角度看,线程共享的Java堆中肯能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB)。
    如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
    方法区(Method Area)
    用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。HotSpot虚拟机使用永久代来实现方法区。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。会抛出OutOfMemoryError异常。
    (https://www.zybuluo.com/HUST-SuWB/note/109933#运行时数据区域)
  4. Java的垃圾回收怎么判断某个对象是否需要回收?
    标记-清除算法
    标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象,它的标记过程其实在前一节讲述对象标记判定时已经基本介绍过了。之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其缺点进行改进而得到的。它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
    复制算法
    为了解决效率问题,一种称为“复制”(Copying)的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为原来的一半,未免太高了一点。
    现在的商业虚拟机都采用这种收集算法来回收新生代,IBM的专门研究表明,新生代中的对象98%是朝生夕死的,所以并不需要按照1∶1的比例来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中的一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次性地拷贝到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8∶1,也就是每次新生代中可用内存空间为整个新生代容量的90%(80%+10%),只有10%的内存是会被“浪费”的。
    标记-整理算法
    复制收集算法在对象存活率较高时就要执行较多的复制操作,效率将会变低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。
    根据老年代的特点,有人提出了另外一种“标记-整理”(Mark-Compact)算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
    分代收集算法
    当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。
  5. ArrayList和LinkedList有什么区别?
    ArrayList是List接口的可变数组的实现。
    LinkedList也和ArrayList一样实现了List接口,但是它执行插入和删除操作时比ArrayList更加高效,因为它是基于链表的。基于链表也决定了它在随机访问方面要比ArrayList逊色一点。
    源码实现参考:
    ArrayList:http://zhangshixi.iteye.com/blog/674856
    LinkedList:http://blog.csdn.net/jzhf2012/article/details/8540543
  6. Set和Map的区别?
    List的功能方法
    实际上有两种List: 一种是基本的ArrayList,其优点在于随机访问元素,另一种是更强大的LinkedList,它并不是为快速随机访问设计的,而是具有一套更通用的方法。
    List : 次序是List最重要的特点:它保证维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(这只推 荐LinkedList使用。)一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和移除元 素。
    ArrayList : 由数组实现的List。允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和移除元素。因为那比LinkedList开销要大很多。
    LinkedList : 对顺序访问进行了优化,向List中间插入与删除的开销并不大。随机访问则相对较慢。(使用ArrayList代替。)还具有下列方 法:addFirst(), addLast(), getFirst(), getLast(), removeFirst() 和 removeLast(), 这些方法 (没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
    Set的功能方法
    Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是 Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责)
    Set : 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
    HashSet : 为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。
    TreeSet : 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。
    LinkedHashSet : 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示
    Map的功能方法
    方法put(Object key, Object value)添加一个“值”(想要得东西)和与“值”相关联的“键”(key) (使用它来查找)。方法get(Object key)返回与给定“键”相关联的“值”。可以用containsKey()和containsValue()测试Map中是否包含某个“键”或“值”。 标准的Java类库中包含了几种不同的Map:HashMap, TreeMap, LinkedHashMap, WeakHashMap, IdentityHashMap。它们都有同样的基本接口Map,但是行为、效率、排序策略、保存对象的生命周期和判定“键”等价的策略等各不相同。
    执行效率是Map的一个大问题。看看get()要做哪些事,就会明白为什么在ArrayList中搜索“键”是相当慢的。而这正是HashMap提高速度的地方。HashMap使用了特殊的值,称为“散列码”(hash code),来取代对键的缓慢搜索。“散列码”是“相对唯一”用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。所有Java对象都能产生散列码,因为hashCode()是定义在基类Object中的方法。
    HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显著提高性能。
    Map : 维护“键值对”的关联性,使你可以通过“键”查找“值”
    HashMap : Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。
    LinkedHashMap : 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。
    TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
    WeakHashMao : 弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。
    IdentifyHashMap : 使用==代替equals()对“键”作比较的hash map。专为解决特殊问题而设计。
  7. Set有哪些?
    List ArrayList 可变数组;保持插入顺序;可重复
    LinkedList 可变链表;保持插入顺序;可重复
    Set HashSet 元素不重复;存储方式很复杂,可以最快获取元素;插入顺序无意义
    TreeSet 元素不重复;升序存储
    LinkedHashSet 元素不重复;保持插入顺序
    Map HashMap 存储方式很复杂,可以最快获取元素;插入顺序无意义
    TreeMap 升序存储
    LinkedHashMap 保持插入顺序;保留HashMap的查询速度
  8. hashMap是怎么实现的?
    源码参考:
    http://blog.csdn.net/jzhf2012/article/details/8540670
    http://zhangshixi.iteye.com/blog/672697
  9. Java的拆箱装箱了解过么,比如int和integer有什么区别?
    简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
    在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法。其他的也类似,比如Double、Character,不相信的朋友可以自己手动尝试一下。
    因此可以用一句话总结装箱和拆箱的实现过程:装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)。
    参考:http://www.cnblogs.com/dolphin0520/p/3780005.html
  10. Java语言对共享资源有哪些解决方案,你知道synchronized关键字么,你知道volatile关键字么,你熟悉Java的并发么?
    参考:
    http://www.cnblogs.com/dolphin0520/category/602384.html
  11. 解释一下Java的static关键字?
    static方法
    static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
    static变量
    static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。static成员变量的初始化顺序按照定义的顺序进行初始化。
    static代码块
    static关键字还有一个比较关键的作用就是用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
  12. 说一下你对SSH框架的理解?
    参考:
    https://www.zybuluo.com/HUST-SuWB/note/88730
    https://www.zybuluo.com/HUST-SuWB/note/93137
    https://www.zybuluo.com/HUST-SuWB/note/102858
  13. Servlet的生命周期?
    Servlet 生命周期:Servlet 加载--->实例化--->服务--->销毁。
    init:在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,负责初始化Servlet对象。可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init()。
    service:它是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。
    Destroy:仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当Servlet对象退出生命周期时,负责释放占用的资源。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。
  14. Tomcat如何处理多个Web工程中依赖的不同版本的jar包?
    默认情况下,Web应用之间的jar包是不会相互影响的,因为其均使用各
    自独立的ClassLoader。
    Tomcat的ClassLoader原理参考:
    http://kyfxbl.iteye.com/blog/1707237
    http://blog.csdn.net/aesop_wubo/article/details/7582266
  15. Webservice的序列化过程是怎样的?
    参考:
    http://www.cnblogs.com/zgqys1980/archive/2013/05/16/3082130.html
  16. (如Lucence /数据库的)索引的数据结构是怎样的?
    局部性原理与磁盘预读
    由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。程序运行期间所需要的数据通常比较集中。
    由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。
    预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。
    B-/+Tree索引的性能分析
    到这里终于可以分析B-/+Tree索引的性能了。
    上文说过一般使用磁盘I/O次数评价索引结构的优劣。先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:
    每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。
    B-Tree中一次检索最多需要h-1次I/O(根节点常驻内存),渐进复杂度为O(h)=O(logdN)。一般实际应用中,出度d是非常大的数字,通常超过100,因此h非常小(通常不超过3)。
    而红黑树这种结构,h明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。
    综上所述,用B-Tree作为索引结构效率是非常高的。
    参考:
    http://blog.csdn.net/v_JULY_v/article/details/6530142
  17. 什么算法能实现从一大段字符串中提取特定子串?
    参考:
    http://www.matrix67.com/blog/archives/115
  18. 在相关的匿名社交软件中,如果我们之间没有直接好友关系,但是通过有限的几个人能够联系上,那么你发的消息我也是能看到的。如果要实现这个功能,要怎么设计?
    参考:
    http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591331.html
  19. 快排的原理和时间复杂度是多少?
    参考:
    http://www.cnblogs.com/liuling/p/2013-7-24-01.html
  20. 怎么判断一个链表有否有环?
    参考:
    http://www.cnblogs.com/zhyg6516/archive/2011/03/29/1998831.html
  21. 给定有序的int数组M,给定int N,如何找出M中任意和等于N的所有组合?
    只有一个有点相关的参考:
    http://www.cnblogs.com/graphics/archive/2010/08/24/1761620.html
  22. 给定两个数int a,int b。在不引入第三个变量的情况下如何交换a与b的值?
  23. 如何不用库类实现比for循环更高效的数组复制?
    其实就是问Ssytem.arrayCopy是怎么实现高效复制数组的
    参考:
    http://blog.163.com/huang_jianhao/blog/static/182480103201201692454830/
  24. 数据库的分页查询是怎么实现的?
    参考:
    http://www.cnblogs.com/QQParadise/articles/1764811.html
  25. 数据库的三范式你了解过么?
    第一范式(确保每列保持原子性)
    第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
    第二范式(确保表中的每列都和主键相关)
    第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
    第三范式(确保每列都和主键列直接相关,而不是间接相关)
    第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
    参考:
    http://www.cnblogs.com/linjiqin/archive/2012/04/01/2428695.html
  26. 数据库的acid你了解过么,数据库执行的过程中有几个要素,你知道么?
    ACID——数据库事务正确执行的四个基本要素
    ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库系统,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易
    原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
    一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的默认规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。、
    隔离性:当两个或者多个事务并发访问(此处访问指查询和修改的操作)数据库的同一数据时所表现出的相互关系。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    持久性:在事务完成以后,该事务对数据库所作的更改便持久地保存在数据库之中,并且是完全的。
    由于一项操作通常会包含许多子操作,而这些子操作可能会因为硬件的损坏或其他因素产生问题,要正确实现ACID并不容易。ACID建议数据库将所有需要更新以及修改的资料一次操作完毕,但实际上并不可行。
    目前主要有两种方式实现ACID:第一种是Write ahead logging,也就是日志式的方式。第二种是Shadow paging。
    参考:
    http://www.2cto.com/database/201305/210060.html
  27. 如何优化你们系统现有的查询速度?
    分页查询,去掉外键,增加索引,优化sql等
  28. tcp三次握手的过程?
    参考:
    http://www.cnblogs.com/rootq/articles/1377355.html
  29. 计算机网络的7层模型知道么?http在哪一层,tcp在哪一层?tcp和udp的区别了解么?为什么需要udp这么一种非面向连接的呢?
    参考:
    http://www.cnblogs.com/fuchongjundream/p/3914236.html
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注