吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3914|回复: 20
收起左侧

[Java 转载] 【笔记】Java基础面试题

  [复制链接]
hack_hu 发表于 2019-8-4 19:40

这段时间在刷「牛客网」的 Java 基础面试题,挑一些里面比较有代表性的题目,和大家分享下我的理解。

类型一:初始化

what:类内部初始化顺序,静态成员、非静态成员、构造器方法是以怎样的顺序完成初始化的?

how? 以下程序会有怎样的输出结果

public class Animal {
    static {
        System.out.println("静态代码块执行");
    }
    Other other  = new Other("非静态");
    static Other staticOther = new Other("静态");
    {
        System.out.println("非静态代码块执行");
    }
    public void sayHi() {
        System.out.println("你好,我是 Animal 类");
    }
    public Animal() {
        System.out.println("兽类被初始化");
    }
    public static void main(String[] args) {
        Animal animal = new Animal();
    }
}

输出:

静态代码块执行
静态Other 类初始化
非静态Other 类初始化
非静态代码块执行
兽类被初始化

在同一类中,先初始静态成员(包括静态代码块)——> 非静态成员 ——> 执行构造器内部操作。同一级别中,按照代码先后顺序执行。

why?

  1. 静态成员不属于任意实例,而是属于类。在我们声明类对象时,静态成员就会执行初始化。Animal  类在加载至内存时,就会自动初始化静态成员,不需要任?***╪ew 构造器)。
  2. 成员优先于构造器内部操作,先初始化(基本类型有对应的默认值,引用类型初始化为 null)。因为构造器(构造函数),可以访问成员变量,在构造器可能会对成员变量进行某些操作,而未赋值的变量编译器是不允许使用的(即编译不通过)。但是编译器的隐式初始化未必是我们想要的值,所以建议我们在定义时初始化或在使用前初始化。
  3. 同一级别中,按照代码先后顺序执行。Java 程序经过编译器编译成字节码,而字节码经过虚拟机解释器转化为机器码,最终变成一条条指令,而计算机执行指令通常是逐行执行的(特殊情况:跳转指令)。

what:继承关系,子类的初始化和父类的初始化有关吗?

how? 以下程序会有怎样的输出结果

public class Animal {
    public Animal() {
        System.out.println("兽类被初始化");
    }
    public static void main(String[] args) {
        Golden golden = new Golden();
    }
}
class Dog extends Animal {
    public Dog() {
        System.out.println("Dog 类被初始化");
    }
}

class Golden extends Dog{
    public Golden(){
        System.out.println("Golden 类被初始化");
    }
}

执行结果:

兽类被初始化
Dog 类被初始化
Golden 类被初始化

在调用子类构造器创建子类实例时,父类无参构造器会先执行。

why?

子类继承了父类所有成员和方法(包括 private 成员),在子类构造器中可以通过 super 显式调用父类的成员和方法。为确保子类在使用时,父类成员可用,要先调用父类构造器,完成父类初始化。

扩展

在子类构造器中会隐式调用父类无参构造器,这是我们未意识到父类构造器的原因(编译器简化我们的代码)。所以,当父类不存在无参构造器时,我们需要显式调用父类构造器,且必须为子类构造器第一条执行语句。

class Dog extends Animal {
    String name;
    public Dog(String name) {
        this.name = name;
        System.out.println("Dog 类被初始化");
    }
}

class Golden extends Dog{
    public Golden(){
        super("金毛");
        System.out.println("Golden 类被初始化");
    }
}

类型二:封装与多态的结合

what: 实例化父类对象却调用子类的构造函数,那执行方法时,调用的是父类方法,还是子类方法,那方法中所调用的成员呢?

how

class Test1 {
    private int id = 12;

    public void printId() {
        System.out.println(idAdd());
    }

    public int idAdd(){
        return id+1;
    }
}

public class Test2 extends Test1 {
    private int id = 1;

    public static void main(String[] args) {
        Test1 test = new Test2();
        test.printId();
    }
}

输出:13

why?

Java 中,调用谁的构造方法,就访问谁的作用域。但是,父类的方法只能访问父类成员。当 子类重写父类方法时,子类作用域调用的就是子类的方法

修改 Test2 代码

public class Test2 extends Test1 {
    private int id = 1;

    public int idAdd(){
        return id+1;
    }
    public static void main(String[] args) {
        Test1 test = new Test2();
        test.printId();
    }
}

此时的输出的答案就是 2。

此时父类 public void printId()  调用的是子类重写的 idAdd(),而子类的 idAdd() 访问的 id 是其本身的成员变量。由于子类方法的重写,二者的答案截然不同,这就是「多态」的一种体现。

类型三:值传递还是引用传递?

what:参数传递,会改变原有变量的值或引用吗?

how? 以下程序会有怎样的输出结果

public void update(String str,char[] chars){
        str = "新字符串";
        chars[0] = '0';
    }
    public static void main(String[] args) {
        Test test = new Test();
        String str = "字符串";
        char[] chars = {'1','2','3'};
        test.update(str, chars);
        System.out.println("str:" + str);
        System.out.println("chars:" + Arrays.toString(chars));
    }

输出结果:

str:字符串
chars:[0, 2, 3]

String 的引用未改变,但是 chars[0] 的值被改变

why?

Java 中所有的参数都是「值传递」,简单说就是「拷贝」(复制)。对于基本类型,就是复制其值,引用类型则复制其引用。

方法中的 str = "新字符串"; 实际上是将传入的引用地址改变,但是原有的 str 引用是没有发生改变的,而 chars 虽然也是复制引用,但是通过下标访问到到的是 chars[0] 实际内存地址,实际修改了它的值。

为了方便理解我将代码改造,并做了标注,方便理解。

引用传递
类似于成语「刻舟求剑」所讲述的故事,虽然在舟上做了丢剑处的标记,但是舟下的那片江却不是丢剑的江了。

三道典型的 Java 基础面试讲完了,没准你有什么不一样的看法或者技巧,欢迎你给出评论,或是默默点点赞给个好看,这都是对我的一种认可。

免费评分

参与人数 11吾爱币 +7 热心值 +10 收起 理由
一人之下123456 + 1 用心讨论,共获提升!
niebaohua + 1 + 1 用心讨论,共获提升!
zhangyongmin + 1 + 1 鼓励转贴优秀软件安全工具和文档!
play1 + 1 我很赞同!
三木零 + 1 + 1 最近有在学Java 赶得早不如赶得巧 哈哈
Keyboard + 1 + 1 谢谢@Thanks!
笑海的星星 + 1 写的很好
Janem + 1 + 1 我很赞同!
胖虎小弟. + 1 + 1 热心回复!
a6107049 + 1 谢谢@Thanks!
13970384692 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| hack_hu 发表于 2019-8-21 16:59
一人之下123456 发表于 2019-8-21 07:37
谢谢楼主,收藏了,刚开始学,有能力了再过来看看。

推荐《Java 核心卷一》,可以做为你 Java 的入门书
 楼主| hack_hu 发表于 2019-8-22 14:58
dmndxld 发表于 2019-8-22 10:47
期待楼主的后续分享!!准大三 还在努力学习

有机会去参加下 ACM,计算机专业只有这个比赛才有含金量
追逐太阳 发表于 2019-8-4 19:50
追逐太阳 发表于 2019-8-4 19:51
有错别字,更正一下吧
13970384692 发表于 2019-8-4 20:04
挺好的,就是错了字,不过无伤大雅
唯殇 发表于 2019-8-4 20:16
学了十多天,看到这些还是不怎么懂
Ryan5 发表于 2019-8-4 21:45
唯殇 发表于 2019-8-4 20:16
学了十多天,看到这些还是不怎么懂

不慌,感觉java是三个月起学的
wxx521 发表于 2019-8-4 22:14
可还行!保存啊
就像风吹过大海 发表于 2019-8-4 22:18
谢谢分享~~
Jayns 发表于 2019-8-4 22:29
可以的,正好用上
henryforsure 发表于 2019-8-4 22:42
牛客确实要多刷
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 13:58

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表