面试姊妹篇5:常见的Java基础面试题

目录

  • [1、
  • [2、
  • 3、关于继承和多态
  • 4、关于finally
  • 5、关于effective final
  • 6、哪一个才是我的属性

系列文章

  • 面试姊妹篇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 4finally

  • 题目描述:下列三组语句的输出你能弄清楚么?
  • 语句一:
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 5effectivefinal

  • 下面的运行结果应该输出什么?
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、输出:编译报错
  • 结论

    • 分清内部类的属性和值

你可能感兴趣的:(面试姐妹篇,面试,java)