java面试整理(会持续更新..)
本人出道至今,经历了大大小小百余场战斗,,,下面整理的面试题有些有答案,有些没答案,那个谁说过:"要抱着怀疑的态度去编程,所以,即便有答案,也不一定正确,即便我本地正确,但是由于屏幕前的你和我本地的开发环境不一样,所以答案可能也会不一样。要静下心来找答案,相信自己的代码,不会有无缘无故的bug"。三年工作经验以下面试大多问基础,三年以上大多问项目经验了。算了,不废话了,直接上干货。。。
另:本人菜逼,下面的问题纯手打或搜索,有不对的地方,欢迎留言指出
干货之前先说一下我架构师室友写的java面试题:
Q:java类的祖先是谁?它有哪些方法?这些方法干什么用?哪些类实现了这些方法?
A:Object类是所有Java类的祖先。toString(),equals(),wait(),hashCode(),finalize()。。。
本人认为大概分为以下几块:
java基础:
1、面向对象的特征和基本原则?
2、java的基本数据类型?什么是自动装箱?自动拆箱?int和Integer有什么区别?
基本数据类型..
3、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?String 是最基本的数据类型吗? float f=3.4;是否正确?
本题还是考查基本数据类型相关的..
4、访问修饰符public,private,protected,以及不写(默认)时的区别?
当前类 同一包 子孙类 其他包
public √ √ √ √
protected √ √ √
default √ √
private √
默认情况下是default
5、&和&&的区别?
&运算符有两种用法:(1)按位与;(2)逻辑与。&&运算符是短路与运算。
二者最大的差别是&&具有短路功能,即:&&左边的表达式为false,就不进行右边的表达式计算了直接返回false。&则两边都是false才返回false
eg:登录时判断用户名不为空且不为空字符串(左右两边的表达式不能互换):username != null &&!username.equals("")
6、解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;
而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代...
方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、"hello"和常量都是放在常量池中,常量池是方法区的一部分。
栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发*Error,而堆和常量池空间不足则会引发OutOfMemoryError。
7、Math.round(10.5) 等于多少?Math.round(-10.5)等于多少?
Math.round(10.5)的返回值是11,Math.round(-10.5)的返回值是-10。四舍五入的原理是在参数上加0.5然后进行下取整。
8、switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
在Java 5以前,switch(expr)中,expr只能是byte、short、char、int。从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java 7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
9、用最有效率的方法计算2乘以8?
2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。
10、数组有没有length()方法?String有没有length()方法?
数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。
11、在Java中,如何跳出当前的多重嵌套循环?
12、构造器(constructor)是否可被重写(override)?
构造器不能被继承,因此不能被重写,但可以被重载。
13、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。
Java对于eqauls方法和hashCode方法是这样规定的:
(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
(2)如果两个对象的hashCode相同,它们并不一定相同。
当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)
14、String和StringBuilder、StringBuffer的区别?
15、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
16、抽象类和接口的区别
17、描述一下JVM加载class文件的原理机制?
JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。
类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化。
包括:(1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;(2)如果类中存在初始化语句,就依次执行这些初始化语句。
类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。
18、char 型变量中能不能存贮一个中文汉字,为什么?
char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16比特),所以放一个中文是没问题的。
19、Java 中会存在内存泄漏吗,请简单描述。
理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。例如Hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露。下面例子中的代码也会导致内存泄露。
import java.util.Arrays; import java.util.EmptyStackException; public class MyStack<T> { private T[] elements; private int size = 0; private static final int INIT_CAPACITY = 16; public MyStack() { elements = (T[]) new Object[INIT_CAPACITY]; } public void push(T elem) { ensureCapacity(); elements[size++] = elem; } public T pop() { if(size == 0) throw new EmptyStackException(); return elements[--size]; } private void ensureCapacity() { if(elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); } } }
上面的代码实现了一个栈(先进后出(FILO))结构,乍看之下似乎没有什么明显的问题,它甚至可以通过你编写的各种单元测试。然而其中的pop方法却存在内存泄露的问题,当我们用pop方法弹出栈中的对象时,该对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,因为栈内部维护着对这些对象的过期引用(obsolete reference)。在支持垃圾回收的语言中,内存泄露是很隐蔽的,这种内存泄露其实就是无意识的对象保持。如果一个对象引用被无意识的保留起来了,那么垃圾回收器不会处理这个对象,也不会处理该对象引用的其他对象,即使这样的对象只有少数几个,也可能会导致很多的对象被排除在垃圾回收之外,从而对性能造成重大影响,极端情况下会引发Disk Paging(物理内存与硬盘的虚拟内存交换数据),甚至造成OutOfMemoryError。
20、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?
都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。
21、阐述静态变量和实例变量的区别。 是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。
22、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?
接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。
23、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?
可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。
24、String s = new String("xyz");创建了几个字符串对象?
两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。
25、GC是什么?为什么要有GC?
答:GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。
26、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?
答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
27、Java 中的final关键字有哪些用法?
答:(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)
28、指出下面程序的运行结果
class A { static { System.out.print("1"); } public A() { System.out.print("2"); } } class B extends A{ static { System.out.print("a"); } public B() { System.out.print("b"); } } public class Hello { public static void main(String[] args) { A ab = new B(); ab = new B(); } }