Java 易错题(持续更新中)

数组易错题

1.判断以下代码的输出结果:

// 判断以下代码的输出结果
int[] arr1 = new int[] {1 , 2 , 3};
System.out.println(arr1);  // 地址

char[] arr2 = new char[] {'a' , 'b' , 'c'};
System.out.println(arr2);  // 遍历数组

原因:PrintStream类中实现了print()方法的重写,只有char类型的数组会直接打印。
在这里插入图片描述
在这里插入图片描述

面向对象易错题

1.多态面试题

class Base {
	public void add(int a, int... arr) {
		System.out.println("base");
	}
}

class Sub extends Base {

	public void add(int a, int[] arr) {
		System.out.println("sub_1");
	}
}


public class InterviewTest1 {

	public static void main(String[] args) {
		Base base = new Sub();
		base.add(1, 2, 3);
	}
}

:在上面的代码中,add()调用的是哪个类中的方法?

解析:这个问题的难点在于子类中的add(int a, int[] arr)是否构成了重写。我们可以在编译器中用重载来试一下public void add(int a, int… arr)和public void add(int a, int[] arr)是否可以共存,如果可以共存,那说明这两个方法是重载方法,不能构成重写。注意重写的概念:子类对父类允许访问的方法,对其实现过程进行重新编写,返回值和形参列表都不变
其实public void add(int a, int… arr)和public void add(int a, int[] arr)在同一个类中是不可以共存的,编译器认为可变参数int …arr等同于int[] arr。所以我们这里是实现了重写的。

答案:既然已经知道了子类构成了重载,那么我们知道,多态访问方法时,运行的是子类重写后的方法,最后输出的结果就是 sub_1。

此题的变形1:

class Base {
	public void add(int a, int... arr) {
		System.out.println("base");
	}
}

class Sub extends Base {

	public void add(int a, int[] arr) {
		System.out.println("sub_1");
	}

	public void add(int a, int b, int c) {
		System.out.println("sub_2");
	}
}


public class InterviewTest1 {

	public static void main(String[] args) {
		Base base = new Sub();
		base.add(1, 2, 3);
	}
}

:在上面的代码中,add()调用的是哪个类中的哪个方法?
解析:这里子类中的add(int a, int b, int c)是个烟雾弹,上面我已经说过了什么是重写,形参列表是不可变的,但是这里的形参列表发生了变化,这就属于子类方法间的重载。我们知道多态调用方法会调用子类重写后的方法,所以最后输出的还是sub1。
答案:sub1

此题的变形2:

class Base {
	public void add(int a, int... arr) {
		System.out.println("base");
	}
}

class Sub extends Base {

	public void add(int a, int[] arr) {
		System.out.println("sub_1");
	}

	public void add(int a, int b, int c) {
		System.out.println("sub_2");
	}
}


public class InterviewTest1 {

	public static void main(String[] args) {
		Base base = new Sub()
		Sub s = (Sub)base;
		s.add(1,2,3);
	}
}

:在上面的代码中,add()调用的是哪个类中的哪个方法?
解析:这个考察的是向下转型,我们已经把base强转成了Sub类,在sub中有两个add方法,当参数个数不确定与参数个数确定的方法都符合调用的条件时,优先调用参数个数确定的方法。
答案:sub_2

2.==和equals有什么区别?
解析:此题最容易出错的地方是equals的说明,我们经常使用String类中的equals方法来比较两个字符串是否相等,但是String类中的equals方法是重写过的。因为经常使用String类中的equals方法,久而久之我们就形成了equals方法是用来比较值是否相等的错误观念。

答案

  • ==可以用来比较基本数据类型和引用数据类型。用来比较基本数据类型时,比较的就是两个变量存储的数值是否相等。如果用来比较引用数据类型,那么比较的就是两个变量的地址值是否相等。
  • equals方法是Object类中定义的方法,如果该方法没有被重写过,那么也是用==来比较两个对象。如果要比较的类中重写了equals方法,那么才会比较类中的属性是否相等。

包装类易错题

1.判断下面代码的执行结果

Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1);

Object o2;
if (true)
	o2 = new Integer(1);
else
	o2 = new Double(2.0);
System.out.println(o2)

解析:我们很容易认为o1的结果是1,其实不对。这个题的易错点是三目运算符,三目运算符要求返回值类型要一致,根据自动类型转换,会把Integer类型的数值转为Double类型。
答案
o1:1.0
o2:1

2.判断下面代码的执行结果

Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);//
Integer m = 1;
Integer n = 1;
System.out.println(m == n);//
Integer x = 128;
Integer y = 128;
System.out.println(x == y);//

解析:首先我们要知道==在比较两个对象的时候,比较的是地址值。new的对象地址值都是不一样的,所以第一个输出打印的是false。难点在于第二个和第三个输出。
我们在Integer的源码中可以看到,Integer定义了一个静态内部类IntegerCache,其中有一个属性时cache[]数组,这个数组存储的是-128-127之间的整数。如果我们定义的数值在这个范围之内,就直接去cache[]数组中取这个数。
在这里插入图片描述
答案:false、true、false

多线程易错题

1.wait()和sleep()有什么异同?
答案:相同:wait()和sleep()都可以使线程进入阻塞状态。
不同:wait()在使线程进入阻塞状态的同时会释放同步锁,sleep()不会;
wait()声明在Object类中,sleep()声明在Thread类中;
wait()只能使用在同步方法或同步代码块中,sleep()可以使用在任何需要调用的场景下。

2.线程的创建方式有几种?
答案:四种。
1)继承Thread类。
2)实现Runnable接口。
3)实现Callable接口。
4)线程池。

字符串易错题

1.String、StringBuffer、StringBuilder的区别?
答案
String:不可变的字符序列;底层使用char[] 数组存储;
StringBuffer:可变的字符序列,线程安全的,效率低;底层使用char[] 数组存储;
StringBuilder:可变的字符序列,JDK 5.0新增,线程不安全,效率高;底层使用char[] 数组存储;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值