对象的赋值是传的地址吗?

rklhxyk1128 2019-08-21 02:09:01


Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1); // 显示内存地址:111
System.out.println(p2); // 显示内存地址:222


然后我让 p1 = p2; 结果打印出来p1和p2的地址都是111,这是为什么呀?
我理解的是赋值把p2的地址指引交给了p1,那应该p1、p2的地址都是222才对吧,为什么都成了p1的地址。而且我用p1.getName()确实是
p2的内容,这是咋回事? 刚学Java不久,麻烦大佬解答下
...全文
3157 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
未知的XY 2019-08-26
  • 打赏
  • 举报
回复
引用 43 楼 憨猪儿的回复:
我的理解是:你开始分别new了一个p1和p2,就是分别给p1和p2分配空间,但是p1和p2都是引用型数据,就是分别指向一个内存中的地址(可以理解为p1和p2分别存的是内存中数据的地址),你让p1=p2(即把p2存的地址赋值给p1),那么他们指向的地址就是同一个地址,所以再输出p1和p2的数据就是一样的。
原来我是个小辣鸡🐔
未知的XY 2019-08-26
  • 打赏
  • 举报
回复
我的理解是:你开始分别new了一个p1和p2,就是分别给p1和p2分配空间,但是p1和p2都是引用型数据,就是分别指向一个内存中的地址(可以理解为p1和p2分别存的是内存中数据的地址),你让p1=p2(即把p2存的地址赋值给p1),那么他们指向的地址就是同一个地址,所以再输出p1和p2的数据就是一样的。
村长的小故事 2019-08-24
  • 打赏
  • 举报
回复
p1和p2都是在栈中存放的都是堆里面的指针,如果p1=p2就是把p2指向的指针现在让p1指了,也就是说现在p1里面现在存放的是之前p2存放的指针,可以了解一下创建对象的过程我想你就明白是怎么回事了,加油!
村长的小故事 2019-08-24
  • 打赏
  • 举报
回复
p1=p2的结果是把老指针指向新引用
luj_1768 2019-08-24
  • 打赏
  • 举报
回复
大多数对象不支持赋值,new 操作是系统为对象分配地址并且执行该类的构造函数。类的底层设计没有包括赋值操作,需要自己写代码才有这种方便的做法。
qq_45414582 2019-08-24
  • 打赏
  • 举报
回复
结果111是对的吧,因为你p1 =p2就是将p2赋值给p1那么他们都会指向p1的内存地址111
晨阳Sylar 2019-08-23
  • 打赏
  • 举报
回复
对象赋值是将不同的对象指向同一内存地址区
rklhxyk1128 2019-08-22
  • 打赏
  • 举报
回复
我刚去翻了下hashcode()文档进一步了解了下,没看到源代码,估计也看不懂。。 其中有几条说明

在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。

实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。

============================

上面说了Hashcode一般把对象内存地址映射成一个整数,如果只和内存地址有关的话估计Hashcode也就唯一了,然而后面说了Java并没这么做。。。
所以他就和底层的内存地址性质不一样了,创建个对象,不管你后面"Show"不"Show",它都在那,内存地址就确定了。而Hashcode就不同了,可以理解创建一个对象他并没有所谓的Hashcode地址,只有调用这个方法才有,也是和之前认知相同的。
Mr_GoodMood 2019-08-22
  • 打赏
  • 举报
回复
只要使用new关键字就会开辟新的对象空间,将新的对象空间的首地址“赋值”给“变量”你这里明显是new了两个对象,对象空间不同,首地址当然不同
rklhxyk1128 2019-08-22
  • 打赏
  • 举报
回复
引用 30 楼 小灰狼 的回复:
除非你的 Person 类重写了 toString() 方法,否则调用 System.out.println(p1) 时,会调用基类的 toString() 方法 在 jdk 安装目录下,有 Object 类的源代码,打开它,可以看到 toString() 方法的实现是:类名 + "@" + 十六进制的哈希值 它看起来很象是内存地址,其实不是,当然,你要当它是地址也没关系,反正 java 里你是无法访问内存地址的
我没有重写方法,是因为我只是多加了一句p1 = p2,然后再次运行造成的这种现象。 而因此也引发了这个问题的延伸思考,你可以看下21、34、35楼,我对内存地址还有Hashcode的区别对吗? 我认为两者的重要区别就是:比如New了p1、p2这两个对象,程序就中断到这暂停,这时候p1、p2是确定了内存地址,但是它们并不拥有Hashcode地址,所以Hashcode并不是随对象的创建而产生的,而是在调用Hashcode()方法再产生(最直观的就是直接打印sout(p)来测试)。 我用的是链接里的addressOf获取内存地址:https://blog.csdn.net/u011089412/article/details/83342028
rklhxyk1128 2019-08-22
  • 打赏
  • 举报
回复
引用 31 楼 qq_39936465 的回复:
[quote=引用 22 楼 rklhxyk1128 的回复:]
对于每次运行涉及变量内存地址不变的情况下,New p1和p2对象,每次运行两者分配的真实内存地址相同,这也很符合逻辑。
但是要用sout打印hashcode地址
先打印p1,那p1的hashcode地址就是111
先打印p2,那p2的hashcode地址就是111
这是后面的问题点,开始我以为hashcode就是真实的底层内存地址,但上面这种现象发现hashcode其实和打印输出的顺序相关,当然它也不是真实内存地址。
详见:https://blog.csdn.net/u011089412/article/details/83342028


都说你的逻辑根本不正确,这里不是输出顺序的问题,我早就说了这里输出默认是调用Object.toString方法,根输出顺序没半毛钱关系。你试试下面的程序就知道。


public class test8 {

public static void main(String[] args) {
// TODO Auto-generated method stub
Person p1=new Person();
Person p2=new Person();
String s1=p1.toString();
String s2=p2.toString();
System.out.println(p1);
System.out.println(p2);
}

}
class Person{
private String name;

public Person(String name) {
super();
this.name = name;
}

public Person() {
super();
}

}



你在把p1,p2反过来输出试试!方法在不调用时是不会执行的,所以造成你觉得是输出顺序的关系,其实跟输出顺序没关系,只是调用方法先后的关系。
[/quote]

我知道你误解在哪了,其实咱们理解都一致的,可能我没表达清楚疑惑点。
你可以往上翻一下,我在12楼就让坛友引导知道了输出默认是调用Object.toString方法,而且我也查到了这个方法返回值最本质调用了hashcode()方法
我的疑惑:【这么优秀的吗, Java不是在New(person对象)的时候分配地址吗,他还会先检测下谁有Print语句(调用hashcode()方法)在分?】

就是说我的疑惑在:以为hashcode就是返回的真实内存地址。所以才会认为Hashcode地址应该在New person()就确定,而不应该和打印(调用hashcode()方法)有关系,这才是我的疑惑点。。。
而后我又查阅资料发现了获取真实内存地址的方法,发现和我最初理解一致,并没有冲突。真实内存地址就是在New对象的时候确定的,而不是hashcode地址那样,在打印(调用hashcode()方法)才产生。

这样我算解释清楚我的问题点了吗,十分感谢你、 能看出你一直想解答我的疑惑,但是我没表达清楚自己疑惑的重点在哪。。。所以你才会认为我没弄明白的是【打印输出顺序和调用方法】 我的问题结的早,要不我会把分都给你, 谢谢大佬!
YaoDaobaba 2019-08-22
  • 打赏
  • 举报
回复
我觉得应该是的
qq_39936465 2019-08-22
  • 打赏
  • 举报
回复
引用 22 楼 rklhxyk1128 的回复:
对于每次运行涉及变量内存地址不变的情况下,New p1和p2对象,每次运行两者分配的真实内存地址相同,这也很符合逻辑。
但是要用sout打印hashcode地址
先打印p1,那p1的hashcode地址就是111
先打印p2,那p2的hashcode地址就是111
这是后面的问题点,开始我以为hashcode就是真实的底层内存地址,但上面这种现象发现hashcode其实和打印输出的顺序相关,当然它也不是真实内存地址。
详见:https://blog.csdn.net/u011089412/article/details/83342028


都说你的逻辑根本不正确,这里不是输出顺序的问题,我早就说了这里输出默认是调用Object.toString方法,根输出顺序没半毛钱关系。你试试下面的程序就知道。


public class test8 {

public static void main(String[] args) {
// TODO Auto-generated method stub
Person p1=new Person();
Person p2=new Person();
String s1=p1.toString();
String s2=p2.toString();
System.out.println(p1);
System.out.println(p2);
}

}
class Person{
private String name;

public Person(String name) {
super();
this.name = name;
}

public Person() {
super();
}

}



你在把p1,p2反过来输出试试!方法在不调用时是不会执行的,所以造成你觉得是输出顺序的关系,其实跟输出顺序没关系,只是调用方法先后的关系。
小灰狼 2019-08-22
  • 打赏
  • 举报
回复
除非你的 Person 类重写了 toString() 方法,否则调用 System.out.println(p1) 时,会调用基类的 toString() 方法 在 jdk 安装目录下,有 Object 类的源代码,打开它,可以看到 toString() 方法的实现是:类名 + "@" + 十六进制的哈希值 它看起来很象是内存地址,其实不是,当然,你要当它是地址也没关系,反正 java 里你是无法访问内存地址的
Zelmira 2019-08-22
  • 打赏
  • 举报
回复
我记得new是临时分配空间的,当你程序运行完了,没有变量指向它后就会被回收。(不知道对不对)
  • 打赏
  • 举报
回复
这不能相等的,EW出来的对象是是存在在堆里面的,他们都是独立存在的,怎么可能相等呢,
rklhxyk1128 2019-08-21
  • 打赏
  • 举报
回复
引用 2 楼 blog.grstudy.com 的回复:
这样就符合逻辑了。。不过我和你操作的不一样。 我是只写了两行打印语句,然后在打印语句之前加上了p1=p2又运行了一遍。 然后我又测试了一下: Person p1 = new Person(); Person p2 = new Person(); System.out.println(p1); // 显示内存地址:111 ========================================== 接着把打印p1换成p2再运行,发现p2内存地址:111 。。。。。 这么优秀的吗, Java不是在New的时候分配地址吗,他还会先检测下谁有Print语句在分?? 这是编译器还是Java的机制呀,能解释下这是什么原理吗
Angeldj 2019-08-21
  • 打赏
  • 举报
回复
没图你说个 毛线
C-A-L-D 2019-08-21
  • 打赏
  • 举报
回复
你的结果不对啊,是重写了toString?
qq2qq2 2019-08-21
  • 打赏
  • 举报
回复
ding ding二楼正解
Licensee:IloveyouAxure
Key:UChpuxwbDW6eAIaAf9UujEFSBwN3vpEz9snHvlCQVJGQy4p7WrCyKLLvV5QLvqva
加载更多回复(23)

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧