黑马程序员技术交流社区
标题: 我被这个问题快搞疯了,求拯救! [打印本页]
作者: 于XINCHENG 时间: 2013-9-7 09:57
标题: 我被这个问题快搞疯了,求拯救!
本帖最后由 于XINCHENG 于 2013-9-9 03:52 编辑
- public class Test01 {
- int a = 1;
- static Test01 testA = new Test01(); // 注意:此处是静态的
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- testA.a = 1;
- testA.testA.a = 2;
- System.out.println(testA == testA.testA); // 注意:此处的输出结果为true,为什么?
- }
- }
复制代码 我被这个问题快搞疯了,求拯救~~~
首先,static Test01 testA = new Test01(); 创建的new Test01()对象是在堆内存还是方法区?
第二,我执行testA.a = 1; 假设是在堆内存中开辟的对象的空间,那么,testA.testA中的第二个testA是方法区中的testA还是堆内存中对象new Test01()的testA?
第三,testA == testA的输出结果为什么是true,我明明创建了两个对象,不应该是true,为什么会这样?
作者: Bad_Boy 时间: 2013-9-7 10:09
方法区;个类中,一个 static 变量只会有一个内存空间,虽然有多个类实例,但这些类实例中的这个static 变量会共享同一个内存空间
作者: 李锡碧 时间: 2013-9-7 10:11
类属性属于整个类,当系统第一次准备使用这个类时,系统会为该类属性分配内存空间,类属性开始生效,直到该类被卸载,该类的类属性所占的内存才被系统的垃圾回收机制回收。类属性生存范围几乎等同于该类的生存范围。
楼上说的对,类实例中的这个static 变量会共享同一个内存空间。
作者: Michael_xpd 时间: 2013-9-7 10:16
new Test01()对象是在堆内存里;第二个testA是堆内存中对象new Test01()的testA;因为testA.testA指的是当前对象的名为testA的对象,还是同一个对象,即testA,所以,最后的输出结果会是true
作者: 于XINCHENG 时间: 2013-9-7 10:17
那请问,static Test01 testA = new Test01(); 的对象是开辟在哪个内存里了?
如果是在方法区中,那里面的int a = 1; 也应该变成static了,和原类Test01中的int a = 1; 不是静态的相矛盾啊
作者: Michael_xpd 时间: 2013-9-7 10:19
我觉得对象应该是在堆内存中的吧?Ps:我是菜鸟,如果说的不对,还请大神多多指教哈!
作者: 于XINCHENG 时间: 2013-9-7 10:20
如果第二个testA是堆内存中的那就说明这个testA不是静态的,和我原对象里面的testA是静态的相矛盾啊
作者: Michael_xpd 时间: 2013-9-7 10:24
对象testA和对象testA.testA是不是同一个对象啊?
作者: 陶智第 时间: 2013-9-7 10:24
第一个问题:
静态方法都是放在方法区中,所以new Test01()对象是在方法区中
第二个问题:
testA.testA中的第二个testA是方法区中的testA,testA.a = 1这句话只是在堆内存中开辟一个空间存放1这个值
第三个问题:
整个程序只有 static Test01 testA = new Test01(); 这句话是创建对象。testA.testA.a = 2;这句话相当于testA.a = 2;
作者: Michael_xpd 时间: 2013-9-7 10:34
static类型的对象被放在共享区,类中的方法区、共享区、数据区都在同一个区;
作者: 于XINCHENG 时间: 2013-9-7 10:45
如果testA在方法区中开辟了对象new Test01()的空间,testA.a = 2; 怎么能又在堆内存中再开辟一次空间,那testA.testA中的第二个testA是哪里来的?
作者: Bad_Boy 时间: 2013-9-7 11:29
这是我理解的
-
无标题.png
(26.17 KB, 下载次数: 8)
应该是这样
作者: 张聪珉 时间: 2013-9-7 12:17
本帖最后由 张聪珉 于 2013-9-7 12:19 编辑
楼主请教,这代码你自己写的?怎么越看越不对劲,对象调用对象自己?我也没看出来哪里有俩对象,我感觉就一个对象testA,就算静态对象可以调用对象自己本身那,返回值还是自身这个对象本身。你理一下思路,有一个对象,是静态的主函数可以直接调用,这个对象是类一加载就已经存在了,new的对象是存在于对内存,某种程度上说这个对象也是只有一个,但是TestA是在方法区或者叫共享数据中,指向了一个对象
作者: 路边小色狼 时间: 2013-9-7 13:16
这代码里你只创建了一个对象,而不管你自己调用自己几次,最终还不是指向内存里的同一个a,那肯定是ture.
作者: 张洪慊 时间: 2013-9-7 14:11
- public class Test01 {
- int a = 1;
- static Test01 testA = new Test01(); //这句话会被编译器分解成两部
- /*
- static Test01 testA;
- static{
- testA=new Test01();
- }
- */
- public static void main(String[] args) {
- testA.testA.a = 2;
- // TODO Auto-generated method stub
- testA.a = 1;
- System.out.println(testA == testA.testA); // 注意:此处的输出结果为true,为什么?
- }
- }
复制代码 静态代码块的特点:随着类的加载而执行,并且只执行一次,优于主函数执行.
testA的类变量在方法区中,引用的是堆内存中的new Test01();
testA.testA.a
关于这句话:testA.testA相当于通过本类对象调用本类的静态成员,特点:被该类的所有对象共享
这个对象A(假设叫A)调用的testA之前已经被初始化(不会再次被初始化,静态成员的初始化是放在静态代码块中,那么也就是说只执行一次)
被初始化的值恰好依然是A...那么我感觉这句话就等价于Test01.testA.a=2;
能力有限,仅供参考.
作者: 影响力147753321 时间: 2013-9-7 14:12
哥们,想知道为什么这样就要知道内存加载的过程。
其实这样的。当主类Test01加载时会先载其静态成员,而加载静态成员分二步,第一是虚拟机本身的静态方法来初始化,把Test01类型的引用变量testA初始化为null。第二步是程序本身对静态变量初始化。这时会生成一个对象,并把地址赋值给引用变量,因为是静态的。所以到此已初始化完毕。以后在也不会在初始化。此时才会加载执行下面代码:
- testA.a = 1;//访问成员变量a,默认为1
- testA.testA.a = 2;//这句意思是可理解为静态加载的对象访问静态成员,(实际上最终还是Test01类访问静态变量,这就是关键,testA.testA 相当于Test01.testA )因为静态只初始化一次。多次访问的是一个地址值,也就是同一个对象。
- 所以最后对象引用比较为true.同一个对象当然为true,
- 上面过程明白了,就知道,生成的对象和其引用都只有一个,引用在方法区中。对象一定在堆中,当然也要说明你也可以在搞一个对象。这个是可以的,但不要用
- testA.testA方式,
作者: 张文豪 时间: 2013-9-8 01:32
首先要明确成员变量和局部变量的区别:成员变量就是方法外部,类的内部定义的变量;
局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。
形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。
成员变量存储在堆中的对象里面,由垃圾回收器负责回收。
其中的 a 是成员变量,存放在堆中,所有new出来的对象都存放在堆中。第一个问题
TestA是静态变量,存放在方法区中,它指向Test01.它并没有存放在堆内存中。第二个问题
TestA和TestA.TestA指的都是TestA这个静态变量,它存放的是new Test01的地址,他们比较当然是true了。第三个问题
作者: 杨增坤 时间: 2013-9-8 07:33
楼主你好!
如果您的问题已经解决了,请把您的问题的未解决更改为已解决!
谢谢合作!
作者: 孔雀东南飞 时间: 2013-9-8 07:47
testA == testA.testA
这里比较的是地址值。
而因为testA是static的,所以该类在内存中只有一个testA,也就是说共享该testA。因此地址值是唯一的,拿自己和自己比较,当然true了。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |