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:总结
尽管大家可能工作了很多年,但是很多基础知识可能压根也不是特别了解或者忘记了,还是要时不时的去回顾,去学习!