写在前面
之前收集整理了一篇《Java线程面试题》,反响还不错,也促使我有了写这篇文章的冲动。
学了好几年的Java,项目也做了一些,总感觉对于很多细小的知识点没有很好地掌握。面临校招,借此机会把遇到的一些常见的Java面试题做一个总结。希望能够巩固自己的Java知识,为面试做好准备。
参考文档:
115个Java面试题和答案——终极列表(上):http://www.importnew.com/10980.html
经典的Java基础面试题集锦:http://www.codeceo.com/article/java-interview-question.html
《Java程序员面试宝典》第11章 面向对象·11.1 面向对象的基本概念:http://www.dushu.com/showbook/101617/1051958.html
JAVA面试题100问第一部分:http://ifeve.com/java-interview-questions-pdf/
面向对象
1.面向对象编程的特征有哪几个方面?
[封装]
封装给对象提供了隐藏内部特性和行为的能力。外部无法直接访问这些封装了的数据,从而保证了这些数据的正确性。同时,对象提供一些能被其他对象访问的方法来改变它内部的数据。在Java当中,有3种修饰符:public,private和protected。每一种修饰符给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。
下面列出了使用封装的一些好处:
-通过隐藏对象的属性来保护对象内部的状态。
-提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。
-禁止对象之间的不良交互提高模块化。
[多态]
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。
[继承]
继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在不修改类的情况下给现存的类添加新特性。
[抽象]
抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。Java支持创建只暴漏接口而不包含方法实现的抽象的类。这种抽象技术的主要目的是把类的行为和实现细节分离开。
2.对象与实例有什么区别?
解析:在Java的内存分配中,对象和实例是不同的,前者分配在内存堆里,后者分配在堆栈里,至于为什么要这样分,参考一下其他的资料。对象是不变的东西,它是对客观事物的抽象,实例是对操作对象的引用,你不能直接操作对象。
答案:对象和实例从宏观的角度看,区别是:对象是同类事物的一种抽象表现形式,而实例是对象的具体化,一个对象可以实例化很多实例,对象就是一个模型,实例是照着这个模型生产的最终产品。实际上就是这样,一个对象可以实例化N个实例。就像根据一个模型可以制造多个实际的产品一样。
Java基础
1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?Java的”一次编写,处处运行”是如何实现的?
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。
2.JDK和JRE的区别是什么?
Java运行时环境(Java Runtime Environment)是将要执行Java程序的Java虚拟机。它同时也包含了执行applet需要的浏览器插件。Java开发工具包(Java Develop Kit)是完整的Java软件开发包,包含了JRE,编译器和其他的工具(比如:JavaDoc,Java调试器),可以让开发者开发、编译、执行Java应用程序。
3.”static”关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法?
“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
4.是否可以在static环境中访问非static变量?
static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
5.Java支持的数据类型有哪些?什么是自动拆装箱?
Java语言支持的8中基本数据类型对应的长度、对应的包装类、:
int--- 4字节---Integer
char---2字节---Character
float---4字节---Float
double---8字节---Double
byte---1字节---Byte
short---2字节---Short
long---8字节---Long
boolean---1字节--Boolean
自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。反之就是自动拆箱。
6.Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?
Java中的方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况。与此相对,方法覆盖是说子类重新定义了父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖者可能不会限制它所覆盖的方法的访问。
7.Java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?
当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。
Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。
Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。
8.Java支持多继承么?
不支持,Java不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。
9.接口和抽象类的区别是什么?
Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于:
接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
类可以实现很多个接口,但是只能继承一个抽象类
类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
抽象类可以在不提供接口方法实现的情况下实现接口。
Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。
也可以参考JDK8中抽象类和接口的区别
10.什么是值传递和引用传递?
对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响源对象的值。
对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象所做的改变会反映到所有的对象上。
11.什么是局域变量?什么是实例变量?什么是类变量(静态变量)?
在方法内、构造函数内或者代码块内定义的变量是局域变量。局域变量在函数内声明和初始化,当函数执行结束时局域变量会被销毁。实例变量是在类中但在任何函数之外的变量。实例变量只有当类实例化后才能被引用。在类中并且在任何函数之外,使用static关键词声明的变量是类变量。
12.什么是类的单例模式?
单例类控制对象的生成,一次只能存在一个对象但兼具灵活性,当条件改变时允许创建多个变量。
13.什么是构造函数?
当一个新的对象被创建的时候会自动调用构造函数。每个类都有构造函数。如果不显性声明构造函数,JAVA编译器会调用默认构造函数。
14.列举为类创建对象的过程(三步)。
首先声明一个对象,然后实例化,再对其初始化。
15.JAVA中字节数据类型的默认值是多少?
0
16.JAVA中float和double的默认值是多少?
float型和double型的默认值与C/C++相同,float是0.0f,double是0.0d。
17.byte类型在什么时候使用?
byte类型用来在较大的数组中节省储存空间。使用byte类型替代int型可以节省三倍的空间。
18.什么是访问控制修饰符?
JAVA提供访问控制修饰符来修饰类、变量、方法和构造函数的访问控制属性。当不写出访问控制修饰符时,成员具有默认的访问权限或者包访问控制权限。
19.什么是受保护访问控制修饰符?
变量、方法和构造函数如果在父类中被声明为受保护,那么它们只能在其它包的子类中或者在该父类的包中被访问。
20.什么是同步修饰符?
JAVA在访问控制修饰符之外还提供同步修饰符,同步修饰符用来限制方法,使方法一次只能被一个线程调用。
21.在JAVA运算符优先级中,哪个运算符的优先级最高?
圆括号()和下标运算符[]具有最高的优先级。
22.在switch语句中能使用的数据类型包括哪些?
switch中使用的变量只能是字节型、短整型、整型或字符型。
23.parseInt()函数在什么时候使用到?
parseInt()函数用于解析字符串返回整数。
24.为什么说String类是不可变的?
String对象一旦被创建就不可改变,因此可以在多个线程中被安全地引用,这对于多线程的编程来说十分重要。
25.为什么说StringBuffer类是可变的?
String类是不可变的,因此一个String对象一旦被创建就不可改变。如果需要对字符串进行频繁的修改,那么就应该使用StringBuffer。
26.StringBuffer和StringBuilder类的区别在哪?
尽可能使用StringBuilder,因为它运行时比StringBuffer快。但如果需要强调线程安全,那就应该使用StringBuffer。
27.如果main方法被声明为private会怎样?
能正常编译,但运行的时候会提示”main方法不是public的”。
28.Java里的传引用和传值的区别是什么?
传引用是指传递的是地址而不是值本身,传值则是传递值的一份拷贝。
29.如果要重写一个对象的equals方法,还要考虑什么?
hashCode。
30.说明一下public static void main(String args[])这段声明里每个关键字的作用
public: main方法是Java程序运行时调用的第一个方法,因此它必须对Java环境可见。所以可见性设置为pulic.
static: Java平台调用这个方法时不会创建这个类的一个实例,因此这个方法必须声明为static。
void: main方法没有返回值。
String是命令行传进参数的类型,args是指命令行传进的字符串数组。
31.如果去掉了main方法的static修饰符会怎样?
程序能正常编译。运行时会抛NoSuchMethodError异常。
32介绍一下final,finally,finalize
final: 常量声明。 finally: 处理异常。 finalize: 帮助进行垃圾回收。
接口里声明的变量默认是final的。final类无法继承,也就是没有子类。这么做是出于基础类型的安全考虑,比如String和Integer。这样也使得编译器进行一些优化,更容易保证线程的安全性。final方法无法重写。final变量的值不能改变。finalize()方法在一个对象被销毁和回收前会被调用。finally,通常用于异常处理,不管有没有异常被抛出都会执行到。比如,关闭连接通常放到finally块中完成。
33.什么是Java API?
Java API是大量软件组件的集合,它们提供了大量有用的功能,比如GUI组件。
34.GregorianCalendar类是什么东西?
GregorianCalendar提供了西方传统日历的支持。
35.为什么Java里没有全局变量?
全局变量是全局可见的,Java不支持全局可见的变量,因为:全局变量破坏了引用透明性原则。全局变量导致了命名空间的冲突。
36.如何将String类型转化成Number类型?
Integer类的valueOf方法可以将String转成Number。下面是代码示例:
String numString = “1000″;
int id=Integer.valueOf(numString).intValue();
37.什么是隐式的类型转化?
隐式的类型转化就是简单的一个类型赋值给另一个类型,没有显式的告诉编译器发生了转化。并不是所有的类型都支持隐式的类型转化。
代码示例:
int i = 1000;
long j = i; //Implicit casting
38.sizeof是Java的关键字吗?
不是。
39.native方法是什么?
native方法是非Java代码实现的方法。
40.在System.out.println()里面,System, out, println分别是什么?
System是系统提供的预定义的final类,out是一个PrintStream对象,println是out对象里面一个重载的方法。
41.显式的类型转化是什么?
显式的类型转化是明确告诉了编译器来进行对象的转化。
代码示例:
long i = 700.20;
int j = (int) i; //Explicit casting
42.类型向下转换是什么?
向下转换是指由一个通用类型转换成一个具体的类型,在继承结构上向下进行。
43.Java的访问修饰符是什么?
访问权限修饰符是表明类成员的访问权限类型的关键字。使用这些关键字来限定程序的方法或者变量的访问权限。它们包含:
public: 所有类都可以访问 protected: 同一个包内以及所有子类都可以访问 private: 只有归属的类才能访问默认: 归属类及相同包下的子类可以访问
44.静态类型有什么特点?
静态变量是和类绑定到一起的,而不是类的实例对象。每一个实例对象都共享同样一份静态变量。也就是说,一个类的静态变量只有一份,不管它有多少个对象。类变量或者说静态变量是通过static这个关键字来声明的。类变量通常被用作常量。静态变量通常通过类名字来进行访问。当程序运行的时候这个变量就会创建直到程序结束后才会被销毁。类变量的作用域和实例变量是一样的。它的初始值和成员变量也是一样的,当变量没被初始化的时候根据它的数据类型,会有一个默认值。类似的,静态方法是属于类的方法,而不是类对象,它的调用并不作用于类对象,也不需要创建任何的类实例。静态方法本身就是final的,因为重写只会发生在类实例上,静态方法是和类绑定在一起的,不是对象。父类的静态方法会被子类的静态方法屏蔽,只要原来方法没有声明为final。非静态方法不能重写静态方法,也就是说,你不能在子类中把一个静态方法改成实例方法。
非静态变量在每一个对象实例上都有单独的一份值。
45.&操作符和&&操作符有什么区别?
当一个&表达式在求值的时候,两个操作数都会被求值,&&更像是一个操作符的快捷方式。当一个&&表达式求值的时候,先计算第一个操作数,如果它返回true才会计算第二个操作数。如果第一个操作数取值为fale,第二个操作数就不会被求值。
46.Java是如何处理整型的溢出和下溢的?
Java根据类型的大小,将计算结果中的对应低阶字节存储到对应的值里面。
47.public static void写成static public void会怎样?
程序正常编译及运行。
48.声明变量和定义变量有什么不同?
声明变量我们只提供变量的类型和名字,并没有进行初始化。定义包括声明和初始化两个阶段String s;只是变量声明,String s = new String(“bob”); 或者String s = “bob”;是变量定义。
49.Java支持哪种参数传递类型?
Java参数都是进行传值。对于对象而言,传递的值是对象的引用,也就是说原始引用和参数引用的那个拷贝,都是指向同一个对象。
50.对象封装的原则是什么?
封装是将数据及操作数据的代码绑定到一个独立的单元。这样保障了数据的安全,防止外部代码的错误使用。对象允许程序和数据进行封装,以减少潜在的干涉。对封装的另一个理解是作为数据及代码的保护层,防止保护层外代码的随意访问。
51.你怎么理解变量?
变量是一块命名的内存区域,以便程序进行访问。变量用来存储数据,随着程序的执行,存储的数据也可能跟着改变。
52数值提升是什么?
数值提升是指数据从一个较小的数据类型转换成为一个更大的数据类型,以便进行整型或者浮点型运算。在数值提升的过程中,byte,char,short值会被转化成int类型。需要的时候int类型也可能被提升成long。long和float则有可能会被转换成double类型。
53.Java的类型转化是什么?
从一个数据类型转换成另一个数据类型叫做类型转换。Java有两种类型转换的方式,一个是显式的类型转换,一个是隐式的。
54.main方法的参数里面,字符串数组的第一个参数是什么?
数组是空的,没有任何元素。不像C或者C++,第一个元素默认是程序名。如果命令行没有提供任何参数的话,main方法中的String数组为空,但不是null。
55.怎么判断数组是null还是为空?
输出array.length的值,如果是0,说明数组为空。如果是null的话,会抛出空指针异常。
56.程序中可以允许多个类同时拥有都有main方法吗?
可以。当程序运行的时候,我们会指定运行的类名。JVM只会在你指定的类中查找main方法。因此多个类拥有main方法并不存在命名冲突的问题。
57.静态变量在什么时候加载?编译期还是运行期?静态代码块加载的时机呢?
当类加载器将类加载到JVM中的时候就会创建静态变量,这跟对象是否创建无关。静态变量加载的时候就会分配内存空间。静态代码块的代码只会在类第一次初始化的时候执行一次。一个类可以有多个静态代码块,它并不是类的成员,也没有返回值,并且不能直接调用。静态代码块不能包含this或者super,它们通常被用初始化静态变量。
58.一个类能拥有多个main方法吗?
可以,但只能有一个main方法拥有以下签名:
public static void main(String[] args) {}
否则程序将无法通过编译。编译器会警告你main方法已经存在。
59.简单的介绍下JVM是如何工作的?
JVM是一台抽象的计算机,就像真实的计算机那样,它们会先将.java文件编译成.class文件(.class文件就是字节码文件),然后用它的解释器来加载字节码。
60.如何原地交换两个变量的值?
先把两个值相加赋值给第一个变量,然后用得到的结果减去第二个变量,赋值给第二个变量。再用第一个变量减去第二个变量,同时赋值给第一个变量。代码如下:
int a=5,b=10;a=a+b; b=a-b; a=a-b;
使用异或操作也可以交换。第一个方法还可能会引起溢出。异或的方法如下: int a=5,b=10;a=a+b; b=a-b; a=a-b;
int a = 5; int b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
61.JVM自身会维护缓存吗,是不是在堆中进行对象分配,操作系统的堆还是JVM自己管理的堆?为什么?
是的,JVM自身会管理缓存,它在堆中创建对象,然后在栈中引用这些对象。
62.==与equals的区别
==比较两个对象在内存里是不是同一个对象,就是说在内存里的存储位置一致。两个String对象存储的值是一样的,但有可能在内存里存储在不同的地方 .
==比较的是引用而equals方法比较的是内容。public boolean equals(Object obj) 这个方法是由Object对象提供的,可以由子类进行重写。默认的实现只有当对象和自身进行比较时才会返回true,这个时候和==是等价的。String, BitSet, Date, 和File都对equals方法进行了重写,对两个String对象 而言,值相等意味着它们包含同样的字符序列。对于基本类型的包装类来说,值相等意味着对应的基本类型的值一样。