Javase面试题
一、选择题
1、以下变量/常量定义符合命名规范的是
A. 变量int num; String name; String adminPassword;
B. 常量final double PI; final int maxCount; final float e;
C. 类class studentInfo; class Employee; class Department;
D. 数组Student students[]; Staff[] staffs; int[] student_scores;
正确答案
A
题目解析
A.都对
B.常量得使用大写字母和_命名
C. 类名必须使用大驼峰命名法
D.数组名必须使用小驼峰命名法,student_scores使用了下划线。
大驼峰命名法和小驼峰命名法是两种常见的变量或函数命名约定:
-
大驼峰命名法(Pascal Case):
- 特点是每个单词的首字母都大写,其余字母小写。
- 例如:
HelloWorld
、MyClass
、UserProfile
。 - 通常用于命名类、枚举、接口等。
-
小驼峰命名法(Camel Case):
- 特点是第一个单词的首字母小写,其余单词的首字母大写。
- 例如:
helloWorld
、myClass
、userProfile
。 - 通常用于命名变量、函数、方法等。
2、以下变量定义正确的是
A. byte b=120; short s=20000; int i = true; long = 99999;
B. byte b=’中’; short s=’享’+1; float f=’思’; double d = ‘途’;
C. byte b=’a’; short s = ‘a’+’b’; char c=128; float f = 888888; double d=1L;
D. byte b=127; boolean bool=0; int i=2200000000; float f = ‘a’f;
正确答案
C
题目解析
A. int i = true不对, long = 99999;也不行没有变量名。
B. byte b = '中'超出了范围
D.boolean bool = 0;int i=2200000000; float f = ‘a’f;都不对
int i=2200000000;
int 类型范围为 -2147483648 到 2147483647, 超出范围
3、下列选项中错误的是?
A. short s1=1;s1=s1+1;
B. short s2=1;s2+=1;
C. int i3=1;i3=i3+1;
D. int i4=1;i4+=1;
正确答案
A
解析如下:
A. short s1=1;s1=s1+1;
错误
- 表达式
s1+1
会先进行整型提升,结果为 int 类型,然后再赋值给 short 类型 s1, 这会造成精度损失。 - 正确的做法应该是:
short s1=1;s1+=1;
B. short s2=1;s2+=1;
正确
s2+=1
是复合赋值运算符,不会发生精度损失。
4、以下说法正确的是
A. if语句的条件表达式必须是一个布尔值,可以是条件运算、逻辑运算,不能是赋值运算。
B. if,while,do...while等语句如果紧跟一条语句或一个语句块时可以省略{}。
C. 在swtich语句中可以接收byte,short,int,long,char等类型的条件表达式,但不能接收布尔型。
D. while与do...while循环的功能和作用完全相同,除了语法上不同,二者并无差别。
正确答案
B
题目解析
A. if的条件表达式可以是布尔类型的赋值运算
C. switch只支持byte, short, int, char, 枚举(JDK1.5)和String(JDK1.7)
D. while的循环体可能一次也不执行,do...while的循环体不能至少执行一次
5、以下说法正确的是
A. 类中可以包含属性、方法、构造方法、块、静态块,但不能包含类。
B. 类的封装是指属性要使用private关键字修饰,并提供公共的get和set方法。
C. 子类继承父类时,可以继承父类的所有属性、方法以及构造方法。
D. 无论类中是否定义了构造方法,编译器都会自动创建一个无参默认构造方法。
正确答案
B
题目解析
A: 类中可以包含类
B:正确
C:不会继承构造方法,但子类构造器调用前会先调用父类构造器
D:默认构造只有在没定义任何构造时才会创建
6、关于面向对象特性说法错误的是
A. 封装是为了保护类的内部不会随意被外部改变。
B. 继承关系下,子类会继承父类的属性、方法、构造方法。
C. 编译时多态是指方法重载带来的多态,在编译时确定调用哪个方法。
D. 运行时多态是指方法重写带来的多态,必须在上转型对象上才会出现。
正确答案
B
题目解析
B. 子类不会继承父类的构造器,但子类创建对象时,会先调用父类构造器,再调用子类的构造器
子类构造器的第一行,默认有super()的调用,即调用父类的无参构造器。
7、下面对this的作用描述错误的是
A. 当成员变量和局部变量重名的时候可以用this区分
B. this()语句必须放在构造方法的第一行,根据this后面括号中的参数调用本类其他的构造方法
C. this可以调用本类的普通方法
D. this可以调用父类的普通方法
正确答案
D
解释如下:
A. 正确。当成员变量和局部变量重名时,可以使用 this
关键字来区分。
B. 正确。this()
语句必须放在构造方法的第一行,根据 this()
后面括号中的参数调用本类其他的构造方法。
C. 正确。this
可以用来调用本类的普通方法。
D. 错误。this
只能用来访问当前类的成员,不能用来调用父类的普通方法。要调用父类的方法,需要使用 super
关键字。
8、以下代码的输出结果是
public class B
{
public static B t1 = new B();
public static B t2 = new B();
{
System.out.println("构造块");
}
static
{
System.out.println("静态块");
}
public static void main(String[] args)
{
B t = new B();
}
}
A. 静态块 构造块 构造块 构造块
B. 构造块 静态块 构造块 构造块
C. 构造块 构造块 静态块 构造块
D. 构造块 构造块 构造块 静态块
正确答案
C
正确的输出顺序:
- 在类加载时,静态成员变量
t1
和t2
被创建,此时还不会执行静态代码块。 - 在
main()
方法中,创建了一个新的B
对象t
。在创建对象之前,会先执行实例初始化块(构造块),输出 "构造块"。 - 然后,调用
B
类的默认构造方法,此时会再次执行实例初始化块,输出 "构造块"。 - 最后,执行静态代码块,输出 "静态块"。
所以,正确的输出顺序是:
构造块
构造块
静态块
构造块
9、下面代码创建了多少个对象
String s = "a"+"c"+""+"d"
A. 1
B. 2
C. 3
D. 4
正确答案
A
题目解析
由于 Java 的字符串常量池优化机制
所以上述代码在编译后为,String s = "acd";
执行过程中,只会创建一个String对象。
10、有如下一段代码,请选择其运行结果
public class StringDemo{
private static final String MESSAGE="situ";
public static void main(String [] args) {
String a ="si"+"tu";
String b="si";
String c="tu";
System.out.println(a==MESSAGE);
System.out.println((b+c)==MESSAGE);
}
}
A. true true
B. false false
C. false true
D. true false
正确答案
D
题目解析
MESSAGE指向常量池中的字符串"situ"
a ="si"+"tu";在编译时进行常量值相加的运算,编译后为 a = “situ”; 也指向常量池中的"situ"
b+c是变量相加,只能在运行时进行拼接,拼接后的字符串会存放在堆中。
== 运算符在针对引用类型时,比较的是两个对象是向指向同一内存地址。
固 a == MESSAGE成立,(b+c) == MESSAGE 不成立。
11、关于集合类型遍历说法正确的是
A. 数组可以使用for循环、增强for循环遍历,遍历时可插入元素来改变数组长度。
B. HashMap集合支持Iterator,所以也可以使用foreach进行遍历。
C. 使用foreach进行遍历时,集合必须实现Iterable接口,遍历过程中不得更改集合中的元素。
D. Set集合可以使用for循环、foreach和迭代器进行遍历。
正确答案
C
题目解析
12、ArrayList list=new ArrayList(20);中的list扩充几次
A. 0
B. 1
C. 2
D. 3
正确答案
A
解释如下:
在 ArrayList list=new ArrayList(20);
这行代码中:
- 我们创建了一个初始容量为 20 的
ArrayList
对象。 ArrayList
在创建时,会根据初始容量来分配内部数组的大小。- 当我们向
ArrayList
中添加元素时,如果当前容量不足,ArrayList
会自动扩容。
但是在这个例子中,由于我们并没有向 ArrayList
中添加任何元素,所以不会触发扩容操作。
因此,答案是 A. 0,即 list
不需要扩容任何次数。
13、关于Map的实现类说法正确的是
A. HashMap允许null值和null键,HashTable允许null键,不允许null值
B. TreeMap底层是采用红黑树实现的,迭代时拥有固定顺序即元素添加时的顺序。
C. ConcurrentHashMap采用链式地址法解决哈希冲突,使用分段锁的方式保存线程安全。
D. HashMap底层采用数组(位桶)+链表+红黑树的方式实现,使用红黑树的目的是为了减少内存的占用。
正确答案
C
题目解析
A. HashTable不允许null键和值
B. TreeMap迭代顺序为Key的自然顺序
C. 正确
D. 红黑树是为了提高元素的查找效率
14、以下对红黑树特性描述不正确的是?
A. 结点必定是红色或黑色的
B. 红黑树的根结点是黑色的
C. 每个黑色结点的子结点都是红色的
D. 从任意一个结点到每个叶子结点都经过相同数量的黑结点
正确答案
C
题目解析
C.红黑树要求红结点的父结点不能是红的。对黑结点没有要求。
红黑树的五个特性为:
1- 结点要么是红的,要么是黑的
2- 根结点是黑的
3- 叶子结点都是null,并且是黑色
4- 红结点的父结点必定是黑结点
5- 任一结点到叶子结点,经过的黑结点的数量是相同的
15、以下关于JAVA语言异常处理描述正确的有?
A. throw关键字可以在方法上声明该方法要抛出的异常。
B. throws用于抛出异常对象。
C. try是用于检测被包住的语句块是否出现异常,如果有异常,则捕获异常,并执行catch语句。
D. finally语句块中的内容,一定会被执行。
正确答案
C
题目解析
A. throw用于抛出一个异常对象
B. throws用于在方法上声明要向上抛出的异常
C. 正确
D. 遇到System.exit(0)时,finally不会执行。
16、关于线程同步说法错误的是
A. 线程并发执行时,可能导致资源访问的冲突,这是线程同步的根本原因。
B. 线程同步可以使用synchronized的关键字实现同步方法和同步代码块。
C. 线程同步时可能会导致死锁问题,死锁问题的解决方式是破坏资源的共享访问。
D. synchronized是非公平锁,ReentrantLock默认是非公平锁,也可以是公平锁。
正确答案
C
解释如下:
A. 正确。线程并发执行时可能会导致资源访问的冲突,这是线程同步的根本原因。
B. 正确。线程同步可以使用 synchronized 关键字实现同步方法和同步代码块。
C. 错误。线程同步时可能会导致死锁问题,但是破坏资源的共享访问并不是解决死锁的根本方法。解决死锁的主要方式包括:
避免资源的循环依赖
合理的资源申请顺序
超时机制
死锁检测和恢复
D. 正确。synchronized 是非公平锁,ReentrantLock 默认也是非公平锁,但是可以设置为公平锁。
17、以下锁机机制中,不能保证线程安全的是
A. Lock
B. synchronized
C. volatile
D. ReadWriteLock
正确答案
C
题目解析
C. volatile只能保证可见性,并且禁止指令重排,但不保证原子性
18、下列代码说法有误的是
A. byte i=100, j=200; 可以通过编译, 整型变量当然可以赋值为整数
B. short s = t = ’a’+1; 可以通过编译, 因为’a’+1会在编译时’a’+1会先被计算
C. final float PI; PI=3.14; 不可以通过编译, 因为PI 是常量,定义时必须赋值
D. char c = 12345; 不可以通过编译,因为整数默认为int类型,不能自动转换为char
正确答案
A,B,C,D
题目解析
A. byte类型的j是不能赋值超-18~127之间的整数
B. 变量t没有声明。
C.PI是float类型的,3.14是double类型的,不能自动转换。
D. char类型可以赋值不
超其表示范围(0~65535)的整数值。
19、以下关于数据类型描述错误的是
A. 隐式数据类型转换是指所有的基本数据类型之间都可以相互转换
B. Java数据类型自动转换时, 不会出现数据的溢出或精度的丢失
C. Java的数据类型自动转换只能是低内存的向高内存的类型转换
D. 布尔类型不支持自动转换, 也不支持强制转换
正确答案
A,B,C
题目解析
A. 自动类型转换只有两条线,byte->short->int->long->float->double, char->int。其它情况不行
B. long转float时,可能出现精度的丢失
C. 自动转换与内存大小无关,是表示范围小的可以自动转换成表达范围大的。
D. 正确
20、方法体内填入以下代码不会报语法错误的是( )
public static void print(int ... param){ 方法体 }
A. param += 10;
B. int size = param.length;
C. param = ‘a’;
D. System.out.println(“参数:”+param)
正确答案
B,D
题目解析
可变参数,在方法体中作为数组使用
A. 数组不可增。
B. 正确,可以取数组的长度
C. 数组不能赋值为字符
D. 正确,数组也可以打印
二、填空题
1、二分查找算法的时间复杂度为__________,快速排序的时间复杂度为__________
正确答案
O(logn),O(nlogn)
2、子类中访问父类的方法可以使用关键字 ( ) 。Java中修饰本地方法的关键字为 ( ) 。
正确答案
super,native
题目解析
super.属性/方法,用于调用父类的属性和方法
native表示 方法是本地方法,也就是C/C++编写的方法,常见于一些底层的类中
3、Map接口的实现类有__________________、__________________、__________________、__________________、__________________。
正确答案
HashMap,HashTable,LinkedHashMap,TreeMap,ConcurrentHashMap,Attributies,Properties
4、类________________是异常处理机制中的根类,它有两个子类________________、________________。
正确答案
Throwable,Error,Exception
5、一个类的对象要进行序列化,必须实现________接口,要忽略某个属性可以使用关键字________修饰
正确答案
Serializable,transient
6、反射中表示属性的类是__________,表示方法的类是____________。
正确答案
Field,Method
题目解析
反射常用类
Class:类的信息,表示一个类
Field:字段,即类中的属性
Method:方法
Constructor:构造器
三、程序题
1、找出下列代码中所有错误并改证,使得代码能够正常运行
public class Staff {
String name;
public Staff(String name) {
this.name = name;
}
public void print() {
System.out.println(this.name);
}
public static void main(String[] args) {
Staff[] staffs = new Staff[3];
staffs[0] = new Staff();
staffs[0].name = "tom";
staffs[1] = new Staff("jerry");
staffs[2].name = "jack";
for (Staff staff : staffs) {
System.out.println(staff.name);
}
}
}
正确答案
staffs[0] = new Staff(); 编译报错,没有无参构造方法,应该与下一行合并写成new Staff(“tom”);
staffs[2].name = "jack"; 运行时报空指针,下标2的元素值为null, 应该写成new Staff(“jack”)
2、请写明该程序编译执行输出结果,如若有问题,请说明错误位置及原因
byte i=-3, j=6;
System.out.println( i & j);
System.out.println( i | j);
System.out.println( i ^ j);
System.out.println( ~ j);
System.out.println( i >> j);
System.out.println( i << j);
System.out.println( i & j);
System.out.println( i | j);
System.out.println( i ^ j);
System.out.println( ~ j);
System.out.println( i >> j);
System.out.println( i << j);
正确答案
4
-1
-5
-7
-1
-192
3、以下程序的输出结果是
public static void main(String[] args){
Integer i1 = 200;
int i2=200;
Integer i3 = new Integer(200);
System.out.print(i1==i2);
System.out.print(i1==i3);
}
正确答案
truefalse
解释如下:
-
Integer i1 = 200;
- 这里使用了自动装箱,
i1
实际上是一个Integer
对象。 - 由于
Integer
的值在-128
到127
之间时会使用缓存,所以i1
和i2
指向同一个对象。 - 因此,
i1 == i2
的结果是true
。
- 这里使用了自动装箱,
-
Integer i3 = new Integer(200);
- 这里创建了一个新的
Integer
对象,和前面的i1
不是同一个对象。 - 因此,
i1 == i3
的结果是false
。
- 这里创建了一个新的
所以, 程序的输出结果是 true false
。
之所以说 i1 == i2
比较的是值,是因为在这种情况下,==
运算符会根据操作数的类型做不同的比较:
-
如果两个操作数都是基本数据类型(如
int
、double
等),那么==
就会比较它们的值是否相等。 -
如果两个操作数都是引用类型(如
Integer
、Double
等),那么==
就会比较它们的引用是否指向同一个对象。
在这个例子中:
i1
是Integer
对象i2
是基本数据类型int
当使用 ==
比较 i1
和 i2
时,因为 i2
是基本数据类型,所以 ==
会比较它们的值,而不是引用。
因为 i1
和 i2
的值都是 200
,所以 i1 == i2
的结果是 true
。
这种情况下,我们可以说 ==
比较的是值,而不是引用。这是因为 Java 在这种情况下会自动拆箱和装箱来完成比较。
4、请写明该程序编译执行输出结果,如若有问题,请说明错误位置及原因
public class Test{
static{
v=5; System.out.print(9);
}
static int v=1;
public Test(){
System.out.print(v);
}
public static void main(String[] args){
System.out.print(v);
Test t= new Test();
}
}
正确答案
911
题目解析
先搞明白类的加载过程
加载:
连接:验证、准备、解析
初始化:
5、请写明该程序编译执行输出结果,如若有问题,请说明错误位置及原因
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
int i=0;
try{
return i++;
} catch (Exception e) {
System.out.println(i);
return i--;
} finally {
System.out.println(i);
return ++i;
}
}
}
正确答案
1
2
四、问答题
1、简述HashMap底层实现
正确答案
HashMap的底层实现:数组+链表
1. HashMap 数组的默认容量16 ,每次扩容 2倍
2. 扩容阈值 0.75 超过16*0.75=12就要扩容
3. 为加快检索效率可能会树化 最小树化阈值 8,即一个链上的元素超过8就对该链进行树化
4. 一支树上的元素低于6个,这个树就会退化成链
5. 最小树化容量阈值 64,数组容量要达到64才能树化
6. 如果数组的长度没有达到64,优先扩容,重新分配存储的位置
2、什么是死锁?死锁的四个必要条件?
正确答案
死锁:多个线程并发执行时,各自占有了部分资源不放弃,又在等待其它线程占用的资源,陷入无限的等待状态
1- 互斥条件:线程对资源的占用是互斥独占的,一个线程占用资源时其它线程不可访问
2- 请求保持:线程占用了一些资源不释放,又要请求占用新的资源
3- 不可剥夺:线程占用资源时,其它线程不可抢夺,只能自己释放
4- 环路等待:多个线程对资源的占用和请求形成环形链
3、什么是类加载器?类加载器有哪些?它们的作用?
正确答案
类加载器是JVM系统中的一部分,主要负责将Java的字节码文件加载到JVM内存中以供执行。
类加载器包括:
启动类加载器:C++编写,负责加载JRE核心类库中的类
扩展类加载器:Java编写,ClassLoader子类,负责加载JRE扩展类库
应用类加载器:Java编写,ClassLoader子类,负责加载当前应用下的类
暂时这些,后面会继续更新