Java| 面试题(2)

面试题1:类初始化和实例初始化

以下代码运行结果:

/**
 * ClassName: Father
 * Date:      2020/2/27 2:10
 * author:    Oh_MyBug
 * version:   V1.0
 */
public class Father {
    private int i = test();
    private static int j = method();	// 父类的静态变量显示赋值代码

    static {
        System.out.print("(1)");	// 父类的静态代码块
    }
    Father(){
        System.out.print("(2)");
    }
    {
        System.out.print("(3)");
    }

    public int test(){
        System.out.print("(4)");
        return 1;
    }
    public static int method(){
        System.out.print("(5)");
        return 1;
    }
}
/**
 * ClassName: Son
 * Date:      2020/2/27 2:13
 * author:    Oh_MyBug
 * version:   V1.0
 */
public class Son extends Father {
    private int i = test();
    private static int j =method();	// 子类的静态变量显示赋值代码
    static {
        System.out.print("(6)");	// 子类的静态代码块
    }
    Son(){
//        super(); // 写或不写都在,在子类构造器中一定会调用父类构造器
        System.out.print("(7)");
    }
    {
        System.out.print("(8)");
    }
    public int test(){
        System.out.print("(9)");
        return 1;
    }
    public static int method(){
        System.out.print("(10)");
        return 1;
    }
    public static void main(String[] args){
        Son s1 = new Son();
        System.out.println();
        Son s2 = new Son();
    }
}

运行结果:

(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2)(9)(8)(7)

考点

  • 类初始化过程
    • 一个类要创建实例需要先加载并初始化该类
      • main方法所在的类需要先加载和初始化
    • 一个子类要初始化需要先初始化父类
    • 一个类初始化就是执行() 方法
      • () 方法由静态类变量显示赋值代码和静态代码块组成
      • 类变量显示赋值代码和静态代码块从上到下顺序执行
      • () 方法只执行一次
  • 实例初始化过程
    • 实例初始化就是执行() 方法
      • () 方法可能重载有多个,有几个构造器就有几个() 方法
      • () 方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成
      • 非静态实例变量显示赋值代码和非静态代码从上到下顺序执行,而对应构造器的代码最后执行
      • 每次创建实例对象,调用对应构造器,执行的就是对应的() 方法
      • () 方法的首行是super() 或super(实参列表),即对应父类的() 方法
  • 方法的重写Override
    • 哪些方法不可以被重写?
      • final方法
      • 静态方法
      • private等子类中不可见方法
    • 对象的多态性
      • 子类如果重写了父类的方法,通过子类对象调用的一定是自类重写过的代码
      • 非静态方法默认的调用对象是this
      • this对象在构造器或者说() 方法中就是正在创建的对象

面试题2:方法的参数传递机制

以下代码运行结果

import java.util.Arrays;

/**
 * ClassName: Exam4
 * Date:      2020/2/27 10:20
 * author:    Oh_MyBug
 * version:   V1.0
 */
public class Exam4 {
    public static void main(String[] args) {
        int i = 1;
        String str = "hello";
        Integer num = 2;
        int[] arr = {1,2,3,4,5};
        MyData my = new MyData();

        change(i,str,num,arr,my);

        System.out.println("i = " + i);
        System.out.println("str = " + str);
        System.out.println("num = " + num);
        System.out.println("arr = " + Arrays.toString(arr));
        System.out.println("my.a = " + my.a);
    }
    public static void change(int j, String s, Integer n, int[] a, MyData m){
        j += 1;
        s += "world";
        n += 1;
        a[0] += 1;
        m.a += 1;
    }
}
class MyData{
    int a = 10;
}

运行结果

i = 1
str = hello
num = 2
arr = [2, 2, 3, 4, 5]
my.a = 11

考点

  • 方法的参数传递机制
  • String、包装类等对象的不变性

方法的参数传递机制

  • 形参是基本数据类型
    • 传递数值
  • 实参是引用数据类型
    • 传递地址值
    • 特殊的类型:String、包装类等对象不可变性

面试题3:递归与迭代

编程题:有n步台阶,一次只能上一步或2步,共有多少种走法?

  • 递归
  • 循环迭代

递归

import org.junit.Test;

/**
 * ClassName: TestStep
 * Date:      2020/2/27 10:44
 * author:    Oh_MyBug
 * version:   V1.0
 */
public class TestStep {
    @Test
    public void test(){
        long start = System.currentTimeMillis();
        System.out.println("result = " + f(40));
        long end = System.currentTimeMillis();
        System.out.println("runtime = " + (end - start));
    }
    // 实现f(n):求n步台阶,一共有几种走法
    public int f(int n){
        if (n < 1){
            throw new IllegalArgumentException(n + "不能小于1");
        }
        if (n == 1 || n == 2){
            return n;
        }
        return f(n-2) + f(n-1);
    }
}

运行结果

result = 165580141
runtime = 1226

循环迭代

import org.junit.Test;

/**
 * ClassName: TestStep1
 * Date:      2020/2/27 11:30
 * author:    Oh_MyBug
 * version:   V1.0
 */
public class TestStep1 {
    @Test
    public void test(){
        long start = System.currentTimeMillis();
        System.out.println("result = " + loop(40));
        long end = System.currentTimeMillis();
        System.out.println("runtime = " + (end - start));
    }
    public int loop(int n){
        if (n < 1){
            throw new IllegalArgumentException(n + "不能小于1");
        }
        if (n == 1 || n== 2){
            return n;
        }
        int one = 2;
        int two = 1;
        int sum = 0;
        for (int i = 0; i < n - 2; i ++) {
            sum = one + two;
            two = one;
            one = sum;
        }
        return sum;
    }
}

运行结果

result = 165580141
runtime = 30

总结

  • 方法调用自身称为递归,利用变量的原值推出新值称为迭代
  • 递归
    • 优点:大问题转化为小问题,可以减少代码量,同时代码精简,可读性好
    • 缺点:递归调用浪费了空间,而且递归太深容易造成堆栈的溢出
  • 迭代
    • 优点:代码运行效率好,因为时间只因循环次数增加而增加,而且没有额外的空间开销
    • 缺点:代码不如递归简洁,可读性好
发布了36 篇原创文章 · 获赞 3 · 访问量 6222

猜你喜欢

转载自blog.csdn.net/Oh_MyBug/article/details/104534591
今日推荐