一道令人疑惑的java基础题

275 阅读2分钟

1:前言

之前看到一题其实很基础,但是可能很多工作了很多年的人还是会做错的题目,所以整理一下记录于此


2:看看题目

2.1 :题目

废话不多说,直接上题目:

随便搞一个bean对象

public class User{
    private Integer id;
    private String name;
    private  Integer age;

    public User(int id, String name, int age) {
        this.id=id;
        this.name=name;
        this.age=age;
    }
}

然后我们来看这个题目的输出

    public static void main(String[] args) {
        int i = 0;
        changeInt(i);
        System.out.println(i);

        Integer ii = 0;
        changeInteger(ii);
        System.out.println(ii);

        String str = "ok";
        changeString(str);
        System.out.println(str);

        String str2 = "ok";
        changeStringNew(str2);
        System.out.println(str2);

        User user = new User(1,"ok",1);
        changeUserName(user);
        System.out.println(user.getName());

        User user2 = new User(1,"ok",1);
        changeUserNameNew(user2);
        System.out.println(user2.getName());
    }

    private static void changeInt(int i) {
        i = 100;
    }

    private static void changeInteger(Integer i) {
        i = 100;
    }

    private static void changeString(String str) {
        str = "changed";
    }

    private static void changeStringNew(String str) {
        str = new String("changed");
    }

    private static void changeUserName(User user) {
        user.setName("changed");
    }

    private static void changeUserNameNew(User user) {
        user = new User(1, "changed", 10);
    }

2.2 :结果

那么让我们来看看结果

  • 0
  • 0
  • ok
  • ok
  • changed
  • ok

怎么样,小伙伴们都答对了吗?

2.3:逐一解析

第一题,第二题:

第一个和第二个应该比较简单,涉及到的知识无非就是java对于基础类型的函数传递是值传递,所以形参复制了一份实参的值去做出了改变,包装类型也会去做自动装拆箱。

第三题,第四题

3,4两题则考察了大家对于String类型的掌握,众所周知,String是final修饰的,引用无法改变。

  String s = new String("ok"); -> 现在堆内存创建一个对象,然后再去str常量池去找有没有创建过
  String s = "ok";  -> 直接就在常量池去找,找不到就新建一个常量,这个引用直接对应到常量池,没有在堆中新建对象

所有和上面的Integer一样,形参其实都是new了一个新的string的引用,所以也没办法改变

第五题,第六题

这2个应该是最让人疑惑的地方了,大家都知道java的对象类型是引用传递,那么第五题是没有问题的,第六题刚刚开始我也搞错了,想当然的以为在函数体内共同改变了同一个引用,其实形参和实参是持有了不同的引用的

步骤是:

  • 实参user持有了[User1]对象
  • 进入函数体,形参user复制了实参的[User1]对象
  • user = new User(1, "changed", 10);
  • 形参user 持有了新的[User2]对象

此时->实参和形参拥有了不同的引用其实。

3:总结

尽管大家可能工作了很多年,但是很多基础知识可能压根也不是特别了解或者忘记了,还是要时不时的去回顾,去学习!