欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java| 面试题(2)

程序员文章站 2022-05-06 17:49:44
...

面试题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、包装类等对象不可变性
Java| 面试题(2)Java| 面试题(2)

面试题3:递归与迭代

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

  • 递归
  • 循环迭代

递归

Java| 面试题(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

循环迭代

Java| 面试题(2)
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

总结

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