目录
系列文章
- 面试姊妹篇1:不起眼的Java陷阱题,一看就会,一做就错
- 面试姊妹篇2:有趣的逻辑面试题分享
- 面试姊妹篇3:常见的Java计算错误
- 面试姊妹篇4:常见的Java多线程面试题
- 面试姊妹篇5:常见的Java基础面试题
3 、 关 于 继 承 和 多 态 \color{7f1A8A}3、关于继承和多态 3、关于继承和多态
- 下面的运行结果应该输出什么?
class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
class B extends A {
public String show(B obj) {
return ("B and B");
}
@Override
public String show(A obj) {
return ("B and A");
}
}
class C extends B {}
class D extends B {}
class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
}
- 结果
1--A and A
2--A and A
3--A and D
4--B and A
5--B and A
6--A and D
7--B and B
8--B and B
9--A and D
- 原因分析:
- 做对这道题,需要你对父类引用子类对象的具体实现有很深的理解,需要理解那些方法会被覆盖,那些会被重写。
- 这道题的具体原因分析见:面向对象编程封装、继承、多态
4 、 关 于 f i n a l l y \color{7f1A8A}4、关于finally 4、关于finally
- 题目描述:下列三组语句的输出你能弄清楚么?
- 语句一:
public class testFinally {
public static String ou = "";
public static void main(String[] args) {
foo(1);
System.out.println(ou);
}
public static void foo(int i) {
try {
if (i == 1) throw new Exception();
ou += "1";
} catch (Exception e) {
ou += "2";
return;
} finally {
ou += "3";
}
ou += "4";
}
}
输出:
23
- 语句二:
public class testFinally {
public static void main(String[] args) {
System.out.println(foo(1));
}
public static String foo(int i) {
String ou = "";
try {
if (i == 1) throw new Exception();
ou += "1";
} catch (Exception e) {
ou += "2";
return ou;
} finally {
ou += "3";
}
ou += "4";
return ou;
}
}
输出:
2
- 语句三:
public class vuhu {
public static void main(String[] args) {
int u = 0;
foo(u);
System.out.println(u);
}
public static void foo(int ou) {
try {
if (1 == 1) throw new Exception();
ou += 1;
} catch (Exception e) {
ou += 2;
return;
} finally {
ou += 3;
}
ou += 4;
}
}
输出:
0
- 结论:
- 语句一和语句二表示,static,静态对象是全局存活的,会记录值。
- 语句二和语句三表示:
- Java是值传递,进入新的栈帧,值不会生效,不会相互传递;
- try、catch、finally之间的调用可能不是一个栈帧,因此没有出现值传递。
5 、 关 于 e f f e c t i v e f i n a l \color{7f1A8A}5、关于effective final 5、关于effectivefinal
- 下面的运行结果应该输出什么?
public class ljtest{
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread name:" + Thread.currentThread().getName() + ",i:" + i);
}
});
}
}
}
- 你期待的:
thread name:Thread-0,i:0
thread name:Thread-1,i:1
thread name:Thread-2,i:2
thread name:Thread-4,i:4
thread name:Thread-6,i:6
thread name:Thread-8,i:8
thread name:Thread-9,i:9
thread name:Thread-3,i:3
thread name:Thread-5,i:5
thread name:Thread-7,i:7
- 实际上:
编译期都过不了,会在输出语句哪一行的 i 哪里显示红线。
- 原因分析
- 因为内部类在访问外部类成员变量的时候,这个变量不能改变,他必须是稳定的,要么是final,要么是effective final。
- final的意思是不可更改的,effective final的意思是差不多相当于不可更改的,如果一个变量在使用前,没有出现过多次赋值(两次),那么就默认是形式上的不可变量。
- 解决办法
- 将变量 i 变成final,或者effective final,例如在for循环下面加上一句:int temp = i;(注意输出语句中的 i 也要改成temp哦)
- 现在将 int temp = i;加上了,结果会是期望那样么?
- 不会,因为线程根本没有启动。
- 解决办法:
- 办法一:在for循环内,每个线程后面加上 t.start();
- 办法二:交给线程池来管理,就不需要加上 t.start();
6 、 哪 一 个 才 是 我 的 属 性 \color{7f1A8A}6、哪一个才是我的属性 6、哪一个才是我的属性
- 下面的运行结果应该输出什么?
public class ljtest {
public final int value = 4;//5.注释掉本行
public void dop(){
int value = 6;//4.注释掉本行
Runnable r = new Runnable() {
public final int value = 9;//3.注释掉本行
@Override
public void run() {
int value = 10;//2.注释掉本行
System.out.println(this.value);//1.去掉this
}
};
r.run();
}
public static void main(String[] args) {
ljtest f = new ljtest();
f.dop();
}
}
- 输出
9
-
看代码的注释部分,考虑下列情形,输出分别是什么?
- //1.去掉this
- //2.注释掉本行
- //3.注释掉本行
- //4.注释掉本行
- //5.注释掉本行
-
输出结果
- 1、输出:10
- 2、输出:9
- 3、输出:6
- 4、输出:4
- 5、输出:编译报错
-
结论:
- 分清内部类的属性和值