美文网首页
我敢打赌你做不了这道java题

我敢打赌你做不了这道java题

作者: 檀木丁 | 来源:发表于2017-03-03 18:22 被阅读181次

java基础题

要是java笔试遇到这个题目,你知道答案吗?

The following program is correct? If wrong, please point out where is wrong. If not please write the answer.
public class TestJava {
    public static void main(String[] args) {
            Other other = new Other();
            new TestJava().addOne(other);
            System.out.println(other.i);
    }
    public void addOne(final Other other) {
            other.i++;
    }
}

class Other {
    public int i;
}

这道题目不难,java基础扎实的,一看便知答案!BUT, 本篇重点是通过这道题,来了解,我们忽略的一些细节。(Follow me!)原谅我的这次BiaoTiDang

容易错误点

上面有困惑的或许是:

  • 在static main方法中能实例化该类本身么?
  • final修饰的变量是能改变的?

针对本题,static修饰方法中,只要Other类型变量是局部的就可以在static方法中实例化。 ===》 没毛病
final修饰的变量不能再重新赋值,但是 other.i++ 操作并没有让other本身在JVM中的地址改变. ===》 没毛病

public class TestJava {
    public static void main(String[] args) {
        Other other1 = new Other();
        System.out.println("other1: " + other1);

        new TestJava().addOne(other1); 
        System.out.println(other1.i);
    }
    public void addOne(final Other other1) {
        System.out.println("other1:111 " + other1);
        other1.i++;
        System.out.println("other1: 222 " + other1);
    }
}

执行结果如下:3处other所标记的内存地址都是一样的。

other1: javaTest.Other@1540e19d
other1:111 javaTest.Other@1540e19d
other1: 222 javaTest.Other@1540e19d
1

针对final疑问点,可以修改如下:

public static void main(String[] args) {
        Other other1 = new Other();
        System.out.println("other1: " + other1);

        Other other2 = new Other();
        System.out.println("other2: " + other2);

        new TestJava().addOne(other1, other2);
        System.out.println(other1.i + ", " + other2.i);
    }
    public void addOne(final Other other1, Other other2) {
        System.out.println("other1: " + other1);
        System.out.println("other2: " + other2);

        //other1.i = other2.i;
        other1 = other2;
        other1.i++;
    }

注意其中的 final, 本段程序会报错,other1 无法 再次赋值 other2

addOne(final Other other1, Other other2) 

java代码执行顺序

问题1

先来看一段代码, 请问一下代码打印多少? 答案在

public class TestJava {
    private static int a = 10;
    {
        a = -1;
        System.out.println("block, a = " + a);
    }
    static {
        System.out.println("static, a = " + a);
    }
    public static void main(String[] args) {
        System.out.println("main, a = " + a);
    }
}

答案是:

static, a = 10
main, a = 10

为何没有 block, a = 10, 因为没有初始化 TestJava这个类!

了解java的,应该知道有关static描述,其中有一句是

static属于类本身, 不属于类的实例。

所以,上述代码执行顺序是,

  • 1.类中的static代码片段
  • 2.static main方法

问题2

再加上一行代码:

public static void main(String[] args) {
        System.out.println("main, a = " + a);
        new TestJava(); //新增代码
    }

答案

static, a = 10
main, a = 10
block, a = -1  //打印出来

类中在方法外的{}语句属于类实例, 会在类构造方法中执行!

为什么这么说? 不信请看 TestJava.class中内容。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package javaTest;

public class TestJava {
    private static int a = 10;

    public TestJava() {
        a = -1;
        System.out.println("block, a = " + a);
    }

    public static void main(String[] args) {
        System.out.println("main, a = " + a);
        new TestJava();
    }

    static {
        System.out.println("static, a = " + a);
    }
}

以上是.class文件在IntellJ IDE上的结果。发现 java源码文件{ }中的内容,跑到TestJava构造方法中了。这个也印证了

java程序没写构造方法,编译器会默认添加一个无参构造方法, 如果添加构造方法后,默认方法消失!

问题3 主动添加构造方法

添加构造方法后的 代码片段:

TestJava(int x) {
        a = x;
        System.out.println("TestJava(x), a = " + a);
    }
.....
public static void main(String[] args) {
        System.out.println("main, a = " + a);
        new TestJava(8); //修改后
    }

运行结果:

static, a = 10
main, a = 10
block, a = -1
TestJava(x), a = 8

通过.class查看 就知道为什么了.

... ...
TestJava(int x) {
        a = -1;
        System.out.println("block, a = " + a);
        a = x;
        System.out.println("TestJava(x), a = " + a);
    }
... ...

java编译器会将外部的{代码片段}包含到构造方法中,并且代码片段位于构造方法顶部。

问题4

要是TestJava中存在多个构造方法,那么 外部的代码片段会在每个构造方法中存在吗? 请看实验!
上述代码再添加无参数构造方法

... ...
public TestJava() {
        System.out.println("TestJava(), a = " + a);
    }
... ...

对应的.class文件显示:

public TestJava() {
        a = -1;
        System.out.println("block, a = " + a);
        System.out.println("TestJava(), a = " + a);
    }

    public TestJava(int x) {
        a = -1;
        System.out.println("block, a = " + a);
        a = x;
        System.out.println("TestJava(x), a = " + a);
    }

{代码片段} 会存在于每一个构造方法中, 而且位置在顶部!

java类中存在多个构造方法,那么 外部的 {代码片段} 会在每个构造方法中存在!

小结

通过以上示例,可以明白java中的几个概念

  • java代码加载顺序: **static { 代码片段 } -> static main方法(如果存在) ->类构造方法(如果存在) 合并外部 {代码片段} **
  • static属于类本身
  • final是不变,但是也可以让内容变

相关文章

  • 我敢打赌你做不了这道java题

    java基础题 要是java笔试遇到这个题目,你知道答案吗? 这道题目不难,java基础扎实的,一看便知答案!BU...

  • 我打赌,这道题你选不对

    前几天,看到同事W在微信朋友圈发了这么一则消息:下午被问到英语语法问题,感受到了自己深深的学渣气质……所以这题,到...

  • 我不爱这个世界 我只爱你

    周末的时候,我窝在床上泪眼蒙胧地看穿越小说,小胖同学一脸挑衅地走了进来:“老妈,我打赌这道数学题你绝对不会。” 我...

  • 2019-05-18

    考试时,你不会这道题,不只是这道题不得分。它会影响你做以后题的心情,情绪,状态等等。进而可能是你,整个考试考的都很...

  • 只有有问题的父母

    “妈妈,这里有一道题我不会做。” “哦?我来看看。” “你看看,这道题和我们昨天做的题有什...

  • 论贫富的教育差距

    “妈,这道题怎么做呀?” “你怎么还在做这一页,这都两小时才做了3个题目,让我看看这道题怎么解,唉!...

  • 【复述练习】宠物

    词汇 betn. 打赌,赌注;被打赌的事物 vt. 打赌;敢断定,确信 vi. 打赌 matronn. 主妇;保姆...

  • leetcode-打开转盘锁

    这道题估计在让我做一次,我还是做不出来的,想不到,且不好理解。 这道题用了BFS,广度优先搜索。利用queue队列...

  • 多线程打印abc问题

    这道题让我想到了操作系统中学的pv操作,下面我先写出这道题pv操作的伪代码。 下面是java写的代码,可以看到两者...

  • 巧求大小

    “啊,这道题怎么做呀!”

网友评论

      本文标题:我敢打赌你做不了这道java题

      本文链接:https://www.haomeiwen.com/subject/nqxrgttx.html