Java面试题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面试题相关的知识,希望对你有一定的参考价值。
一个.java源文件中是否可以包含多个类(不是内部类),有什么限制
可以有多个类,但只能有一个public类,并且public的类名必须与文件名一直
Java有没有goto
goto是Java中的保留字,目前版本的Java没有使用
说说&和&&的区别
都可以用作逻辑运算符与(and),需要运算符两边的表达式结果为true时,运算结果才会为true;不同的是&&具有短路的功能,即第一个表达式为false,则不再计算后面的表达式,列如str!=null&&!str.equals(“”),当str为null时,后面的表达式就不会计算,如果把&&改成&,则会抛出空指针异常(NullPointerException)
Java中如何跳出当前的多重嵌套循环
在最外层循环前加一个标记A,然后用break A;可以跳出多重循环
switch语句能否作用在byte上,能否作用在long上,能否作用在String上
Java5以前switch(expr)中expr只能是byte、short、char、int,Java5开始支持枚举类型,Java7开始支持字符串(String),而长整型(Long)在目前所有版本中都不可以
float f=3.4;是否正确
不正确,3.4是双精度(double),将双精度型赋值给浮点型属于下转型(down-casting)会造成精度损失,因此需要强制类型转换(float f=(float)3.4;或者float f=3.4F;)
short s1=1;s1=s1+1;有什么错;short s1=1;s1+=1;有什么错
对于short s1=1;s1=s1+1;由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型的s1时,编译器将报需要强制转换类型的错误;对于short s1=1;s1+=1;由于+=是Java语言规定的运算符,Java编译器会对它进行特殊处理,因此可以正确编译
char型变量中能不能存储一个中文汉字,为什么
char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode,一个char类型占2个字节(16比特),放一个中文没有问题
用最有效率的方法算出2乘以8等于几
2<<3
将一个数左移n位,相当于乘以了2的n次方
请设计一个一百亿的计算器
---
使用final关键字修饰一个变量时,是引用不能变还是引用的对象不能变
使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的
==和equals方法究竟有什么区别
值类型的变量是存储在内存中的栈,而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中,==操作比较的是两个变量的值是否相等,对于引用类型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同,equals表示的变量是否是对同一个对象的引用,即堆中的内容是否相同,==比较的是两个对象的地址,而equals比较的是两个对象的内容
静态变量和实例变量的区别
语法定义上的区别:静态变量前要加static关键字,而实例变量则不加
程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量;静态变量并不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,就可以被使用(实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用)
是否可以从一个static方法内部发出对非static方法的调用
不可以,因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用
如何实现对象的克隆
实现Cloneable接口并重写Object类的clone()方法
实现Serializable接口,通过序列化和反序列化实现克隆,可以实现真正的深度克隆
Integer和int的区别
int是Java提供的原始数据类型,Integer是Java为int提供的封装类(int的默认值是0,Integer的默认值是null),Java5开始引入了自动装箱/拆箱机制,使得二者可以互相转换
byte:Byte
short:Short
int:Integer
long:Long
float:Float
double:Double
char:Character
boolean:Boolean
public static void main(String[] args) {
Integer a = new Integer(3);
Integer b = 3; // 将3自动装箱成Integer类型
int c = 3;
System.out.println(a == b); // false 两个引用没有引用同一对象
System.out.println(a == c); // true a自动拆箱成int类型再和c比较
}
public static void main(String[] args) {
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);//true
System.out.println(f3 == f4);//false
//如果整型字面量的值在-128到127之间,则不会new新的Integer对象
}
Math.round(11.5)等于多少;Math.round(-11.5)等于多少
Math类提供了三个与取整有关的方法:ceil、floor、round
Math.ceil(11.5)等于12;Math.ceil(-11.3)等于-11;
Math.floor(11.3)等于11;Math. floor (-11.3)等于-12;
Math.round(11.5)等于12;Math.round(-11.5)等于-11;
访问修饰符public、protected、default、private的作用域
修饰符 当前类 当前包 子类 其他包
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
重载(overload)和重写(override)的区别
重载(overload)发生在同一个类中,同名的方法有不同的参数列表(参数的个数或类型不同)
重写(override)发生在子类和父类之间,要求子类重写的方法与父类被重写方法(方法名称相同)有相同的返回类型,相同的参数列表
方法重载,为什么不能根据返回值类型来区分
因为调用时不能指定类型信息,编译器不知道要调用哪个函数
构造器(constructor)是否可被重写(override)
构造器不能被继承,因此不能被重写(override),但可以被重载(overload)
接口是否可继承接口,抽象类是否可实现(implements)接口,抽象类是否可继承具体类(concrete class),抽象类中是否可以有静态的main方法
接口可以继承接口,抽象类可以实现接口,抽象类可以继承具体类,抽象类中可以有静态的main方法
当clone()方法时,通常都有一行代码,是什么
super.clone();
首先要把父类中的成员复制到位,然后才是复制自己的成员
面向对象的特征有哪些
抽象:将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象,只关注对象有哪些属性和行为,不关注行为的细节
封装:把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口
继承:从已有类得到继承信息创建新类的过程,提供继承信息的类成为父类,得到继承信息的类成为子类
多态:允许不同子类型的对象对同一消息做出不同的响应,方法的重载和方法的重写是实现多态的两种方式
Java中实现多态的机制是什么
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象
抽象类(abstract class)和接口(interface)的区别
抽象类和接口都不能够实例化,一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要声明为抽象类
抽象类可以定义构造器,可以有抽象方法和具体方法,而接口不可以定义构造器而且其中的方法全都是抽象方法;抽象类的成员可以是public、default、protected、private,而接口中的成员只能是public;抽象类种可以定义成员变量,而接口中成员变量实际上都是常量(有抽象方法的类必须声明为抽象类,而抽象类不一定有抽象方法)
abstract method是否可同时是static,是否可同时是native,是否可同时是synchronized
abstract method不可以是static的,因为抽象的方法是要被子类实现的
什么是内部类,Static Nested Class和Inner Class有什么不同
静态嵌套类是被声明为静态的内部类,可以不依赖于外部类实例被实例化;而内部类通常需要在外部类实例化后才能实例化
内部类可以引用它的包含类的成员吗,有没有什么限制
一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员
Java中的final关键字有哪些用法
修饰类:表示该类不能被继承;修饰方法:表示方法不能被重写;修饰变量:表示变量只能一次赋值以后值都不能被修改
指出下面程序的运行结果
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();
}
}
1a2b2b,先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器
匿名内部类(Anonymous Inner Class)是否可以继承(extends)其他类,是否可以实现(implements)接口(interface)
可以继承其他类或实现其他接口,不仅是可以,而是必须
super.getClass()方法调用,下列程序的输出结果是多少(Test)
public class Test extends Date {
public static void main(String[] args) {
new Test().test();
}
public void test() {
System.out.println(super.getClass().getName());
}
}
由于getClass()在Object类中定义成了final,子类不能覆盖该方法,所以,在test方法中调用getClass().getName()时,其实就是在调用从父类继承的getClass()方法,等效于调用super.getClass().getName方法,所以返回的应该是Test
如果想要得到父类的名称,应该用如下代码:
getClass().getSuperClass().getName();
String是最基本的数据类型吗
不是,基本的数据类型包括:byte、short、int、long、float、double、char、boolean
String s=”Hello”;s=s+”world”;这两行代码执行后,原始的String对象中的内容改变了没有
没有,因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象,这段代码执行后,只是改变了s的指向,s不再指向原来的对象,而是指向了另一个内容为“Hello world”的String对象,而原来的那个对象还存在于内存中
是否可继承String类
String类是final类,不可以被继承
当一个对象被当做参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里是值传递还是引用传递
是值传递,Java语言的方法调用只支持参数的值传递
String s=new String(“xyz”);创建了几个对象
两个,一个静态区的“xyz”,一个new创建在堆上的对象
如何将字符串转换为基本数据类型,如何将基本数据类型转换为字符串
调用基本数据类型对应的包装类的parseXXX(String)或者valueOf(String)即可返回相应的基本类型;一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串,另一种方法是调用String类中的valueOf()方法返回相应的字符串
用递归实现字符串反转
public static String reverse(String originStr){
if(originString==null||originStr.length()<=1){
return originStr;
}
Return reverse(originString.substring(1))+originStr.charAt(0);
}
怎么将GB2312编码的字符串转换为ISO-8859-1
String s1=”hello”;
String s2=new String(s1.getBytes(“GB2312”),”ISO-8859-1”);
如何获得年月日小时分钟秒;如何取得从1970年1月1日0时0分0秒到现在的毫秒数;如何获得某月的最后一天;如何格式化日期
LocalDateTime dt=LocalDateTime.now();
dt.getYear();
dt.getMonthValue();
dt.getDayOfMonth();
dt.getHour();
dt.getMinute();
dt.getSecond();
System.currentTimeMillis();
Calendar time=Calendar.getInstence();
time.getActualMaximum(Calendar.DAY_OF_MONTH);
//SimpleDateFormat oldFormatter=new SimpleDateFormat(“yyyy/MM/dd”);
//Date date1=new Date();
//oldFormatter.format(date1);
DateTimeFormatter newFormatter=DateTimeFormatter.ofPattern(“yyyy/MM/dd”);
LocalDate date2=LocalDate.now();
date2.format(newFormatter);
打印昨天的当前时刻
LocalDateTime today=LocalDateTime.now();
LocalDateTime yesterday=today.minusDays(1);
System.out.println(yesterday);
比较一下Java和JavaScript
---
String和StringBuffer的区别
String是不可变的对象,每次对String类型进行改变都相当于产生了一个新的对象,StringBuffer是可变的字符序列,所以如果要经常改变某个字符串的话建议使用StringBuffer
如何把一段逗号分隔的字符串转换成一个数组
String[] result=orgStr.split(“,”);
数组有没有length()这个方法,String有没有length()这个方法
数组没有length()方法,但是有length属性,String有length()方法
下面这条语句一共创建了多少个对象:String=”a”+”b”+”c”+”d”;
只创建了一个String对象
Javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个常量相连的结果
Try{}里面有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后
会被执行,finally中的代码比return和break语句后执行
下面的程序代码输出的结果是多少
public static void main(String args[]) {
Test t = new Test();
int b = t.get();
System.out.println(b);
}
public int get() {
try {
return 1;
} finally {
return 2;
}
}
(首先返回1,然后被2覆盖)返回的结果是2,try中的return语句调用的函数先于finally中调用的函数执行,也就是说return语句先执行,finally语句后执行,return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回
final、finally、finalize的区别
final:修饰符,修饰类表示该类不可被继承,修饰变量,表示该变量不被改变(常量),修饰方法,表示不能在子类中被重写
finally:通常放在try…catch的后面构造总是执行代码块,无论程序正常执行还是发生异常,只要JVM不关闭这里的代码都能执行
finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作
运行时异常和一般异常(受检异常)有何异同
异常表示程序运行过程中可能出现的非正常态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误;Java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常
error和exception有什么区别
error表示系统级的撮合和程序不必处理的异常,是恢复不是不可能单很困难的情况下的一种严重问题,比如内存溢出,不可能指望程序能处理这样的情况;exception则表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题,表示如果程序运行正常,从不会发生的情况
下面哪些是Thread类的方法(ABD)
A、start()
B、run()
C、exit()
D、getPriority()
exit()是System类的方法
下面关于java.lang.Exception类的说法正确的是(A)
A、继承自Throwable
B、Serialable
Java.lang.Error和java.lang.Exception继承自Throwable
具体的Exception(如RuntimeException)继承自Exception
具体的RuntimeException继承自RuntimeException
java.lang.Error与java.lang.Exception的区别
下面程序的运行结果是(false、true)
String str1=”hello”;
String str2=”he”+new String(“llo”);
System.out.prinln(str1==str2);
System.out.prinln(str1.equals(str2));
str2中的”llo”是新申请的内存块,而==判断的是对象的地址而非值,所以是false
如果是String str2=str1,那么就是true了
下列说法正确的有(C)
A、class中的constructor不可省略
B、constructor必须与class同名,但方法不能与class同名
C、constructor在一个对象被new时执行
D、一个class只能定义一个constructor
这里可能会有误区,其实普通的类方法是可以和类同名的,和构造方法的唯一区分就是构造方法没有返回值
具体的选项不记得,但用到的知识如下
String[] a=new String[10];则a[0]~a[9]=null;a.length=10;
int[] a=new int[10];则a[0]~a[9]=0;a.length=10;
下面程序的运行结果:pongping(如果是start()的话就是pingpong)
public static void main(String args[]) {
Thread t = new Thread() {
public void run() {
pong();
}
};
t.run();
System.out.print("ping");
}
static void pong() {
System.out.print("pong");
}
start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程,进而调用run()方法来执行任务,而单独调用run()就跟调用普通方法一样,已经失去了线程的特性了。因此在启动一个线程的时候一定要使用start()而不是run()
下面属于关系型数据库的是(AB)
A、Oracle
B、mysql
C、IMS
D、MongoDB
关系型数据库:DB2、Oracle、MySQL等
层次型数据库:IMS、MongoDB、Redis等
GC线程是否为守护线程(是)
只要当前JVM实例中尚存在任何一个非守护线程(用户线程)没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作;GC是守护线程最典型的应用
volatile关键字是否能保证线程安全(不能)
volatile关键字用在多线程同步中,可保证读取的可见性,无法保证线程安全
下列说法正确的是(AC)
A、LinkedList继承自List
B、AbstractSet继承自Set
C、HashSet继承自AbstractSet
D、WeakMap继承自HashMap
存在i+1<1的数吗(存在)
如果i为int型,那么当i为int能表示的最大整数时,i+1就溢出变成负数了
存在i>j||i<=j不成立的数吗(存在)
比如Double.NaN或Float.NaN
0.6332的数据类型是(B)
A、float
B、double
C、Float
D、Double
下面那个流类属于面向字符的输入流(D)
A、BufferedWriter
B、FileInputStream
C、ObjectInputStream
D、InputStreamReader
Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式
面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和OutputStream的子类
面向字符的操作为以字符为单位对数据进行操作,在读的时候将二进制数据转为字符,在写的时候将字符转为二进制数据,这些类都是Reader和Writer的子类
InputStream(输入)、OutputStream(输出)为后缀的是字节流
Reader(输入)、Writer(输出)为后缀的是字符流
Java接口的修饰符可以为(CD)
A、private
B、protected
C、final
D、abstract
接口用于描述系统对外提供的所有服务,因此接口中的成员变量和方法都必须是公开(public)类型,确保外部使用者能访问到它们
接口仅仅是描述系统能做什么,但不指明如何去做,所以接口中的方法都是抽象(abstract)方法
接口不涉及和任何具体实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量,只有静态(static)变量
接口中的变量是所有实现类共有的,既然是共有,肯定是不变的,所以变量是不可变类型(final)类型,也就是常量
接口的方法默认是public abstract
接口的属性默认是public static final常量,且必须赋初值
注意:final和abstract不能同时出现
不通过构造函数也能创建对象吗(是)
Java创建对象的方式有:new语句创建对象;运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法;调用对象的clone()方法;运用反序列化手段,调用java.io.ObjectInputStream对象的readObject方法
ArrayList list=new ArrayList(20);中的list扩充了几次(0)
ArrayList的长度是10,所以如果要往list里添加20个元素肯定要扩充一次(扩充为原来的1.5倍),但是当指明了需要多少空间,就一次性为你分配这么多空间,也就是不需要扩充
下面哪些是对称加密算法(AB)
A、DES
B、AES
C、DSA
D、RSA
常见的对称算法有:DES、3DES、RC2、RC4、AES
常见的非对称算法有:RSA、DSA、ECC
使用单向散列函数的加密算法有:MD5、SHA
新建一个流对象,下面哪个选项的代码是错误的(B)
A、new BufferedWriter(new FileWriter(“a.txt”));
B、new BufferedReader(new FileInputStream(“a.dat”));
C、new GZIPOutputStream(new FileOutputStream(“a.zip”));
D、new ObjectInputStream(new FileInputStream(“a.dat”));
注意:Reader只能用FileReader进行实例化
下面程序能正常运行吗(能)
public class NULL {
public static void haha(){
System.out.println("haha");
}
public static void main(String[] args) {
((NULL)null).haha();
}
}
null值可以强制转换为任何java类类型,(String)null也是合法的,但null强制转换后是无效对象,其返回值还是null,而static方法的调用是和类名绑定的,不借助对象进行访问所以能正确输出,如果没有static修饰就只能用对象访问,使用null调用对象就肯定会报空指针错误了
下面程序的运行结果是什么(static A static B I’m A class HelloA I’m B class HelloB)
class HelloA {
public HelloA() {
System.out.println("HelloA");
}
{ System.out.println("I‘m A class"); }
static { System.out.println("static A"); }
}
public class HelloB extends HelloA {
public HelloB() {
System.out.println("HelloB");
}
{ System.out.println("I‘m B class"); }
static { System.out.println("static B"); }
public static void main(String[] args) {
new HelloB();
}
}
考察静态语句块、构造语句块(只有大括号那块)以及构造函数的执行顺序
注意:static语句执行完后才执行main方法
getCustomerInfo()方法如下,try中可以捕获三种类型的异常,如果在该方法运行中产生了一个IOException,将会输出什么结果(A)
public void getCustomerInfo() {
try {
// do something that may cause an Exception
} catch (java.io.FileNotFoundException ex) {
System.out.print("FileNotFoundException");
} catch (java.io.IOException ex) {
System.out.print("IOException");
} catch (java.lang.Exception ex) {
System.out.print("Exception");
}
}
A、IOException
B、IOException Exception
C、FileNotFoundException IOException
D、FileNotFoundException IOException Exception
当用多个catch语句时,catch语句块在次序上有先后之分,从前面的catch语句块依次先后进行异常类型匹配,如果父异常在子异常类之前,那么首先匹配的将是父异常类,子异常类将不会获得匹配的机会,一般父类异常类即Exception放在catch语句块的最后一个(父类异常放前面编译是不通过的)
下面代码的运行结果是(C)
public static void main (String[] args){
String s;
System.out.println("s=" + s);
}
A、代码得到编译,并输出“s=”
B、代码得到编译,并输出“s=null”
C、由于String s没有初始化,代码不能编译通过
D、代码得到编译,但捕获到NullPointException异常
Java中所有定义的基本类型或对象都必须初始化才能输出值
System.out.println(“5”+2);的输出结果应该是(A)
A、52
B、7
C、2
D、5
Java会自动将2 转换为字符串
支出下列程序运行的结果(B)
public class Example {
String str = new String("good");
char[] ch = { ‘a‘, ‘b‘, ‘c‘ };
public static void main(String args[]) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = ‘g‘;
}
}
A、good and abc
B、good and gbc
C、test ok and abc
D、test ok and gbc
Java里没有引用传递,只有值传递
要从文件“file.bat”中读出第10个字节到变量c中,下列哪个方法适合(A)
A、FileInputStream in=new FileInputStream(“file.bat”);in.skip(9);int c=in.read();
B、FileInputStream in=new FileInputStream(“file.bat”);in.skip(10);int c=in.read();
C、FileInputStream in=new FileInputStream(“file.bat”);int c=in.read();
D、RandomAccessFile in=new RandomAccessFile(“file.bat”);in.skip(9);int c=in.readByte();
下列哪种异常是检查型异常,需要在编写程序时声明(C)
A、NullPointedException
B、ClassCastException
C、FileNotFoundException
D、IndexOutOfBoundsException
下面的方法,当输入为2时返回值是多少(D)
public static int getValue(int i) {
int result = 0;
switch (i) {
case 1:
result = result + i;
case 2:
result = result + i * 2;
case 3:
result = result + i * 3;
}
return result;
}
A、0
B、2
C、4
D、10
注意case后面没有加break,所以从case2 一直运行下去
选项中哪一行代码可以替换题目中//add code here而不产生编译错误(A)
public abstract class MyClass {
public int constInt = 5;
//add code here
public void method() {}
}
A、public abstract void method(int a);
B、constInt=constant+5;
C、public int method();
D、public abstract void anotherMethod(){}
考察抽象类的使用
阅读Shape和Circle两个类的定义,在序列化一个Circle的对象到文件时,下面哪个字段会被保存到文件中(B)
class Shape {
public String name;
}
class Circle extends Shape implements Serializable{
private float radius;
transient int color;
public static String type = "Circle";
}
A、name
B、radius
C、color
D、type
下面是People和Child类的定义和构造方法,每个构造方法都输出编号,在执行new Child(“mike”)的时候都有哪些构造方法被顺序调用,请选择输出的结果(D)
class People {
String name;
public People() {
System.out.print(1);
}
public People(String name) {
System.out.print(2);
this.name = name;
}
}
class Child extends People {
People father;
public Child(String name) {
System.out.print(3);
this.name = name;
father = new People(name + ":F");
}
public Child() {
System.out.print(4);
}
}
A、312
B、32
C、432
D、132
在Java中,子类的构造过程中必须调用其父类的构造函数
以上是关于Java面试题的主要内容,如果未能解决你的问题,请参考以下文章
2020年1-6月份Java面试题总结,20多类1100道面试题含答案解析