黑马程序员技术交流社区

标题: 我被这个问题快搞疯了,求拯救! [打印本页]

作者: 于XINCHENG    时间: 2013-9-7 09:57
标题: 我被这个问题快搞疯了,求拯救!
本帖最后由 于XINCHENG 于 2013-9-9 03:52 编辑
  1. public class Test01 {
  2.         int a = 1;
  3.         static Test01 testA = new Test01(); // 注意:此处是静态的
  4.         public static void main(String[] args) {
  5.                 // TODO Auto-generated method stub
  6.                 testA.a = 1;
  7. testA.testA.a = 2;
  8.                 System.out.println(testA == testA.testA); // 注意:此处的输出结果为true,为什么?
  9. }
  10. }
复制代码
我被这个问题快搞疯了,求拯救~~~

首先,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
Bad_Boy 发表于 2013-9-7 10:09
方法区;个类中,一个 static 变量只会有一个内存空间,虽然有多个类实例,但这些类实例中的这个static 变 ...

那请问,static Test01 testA = new Test01(); 的对象是开辟在哪个内存里了?
如果是在方法区中,那里面的int a = 1; 也应该变成static了,和原类Test01中的int a = 1; 不是静态的相矛盾啊

作者: Michael_xpd    时间: 2013-9-7 10:19
Bad_Boy 发表于 2013-9-7 10:09
方法区;个类中,一个 static 变量只会有一个内存空间,虽然有多个类实例,但这些类实例中的这个static 变 ...

我觉得对象应该是在堆内存中的吧?Ps:我是菜鸟,如果说的不对,还请大神多多指教哈!
作者: 于XINCHENG    时间: 2013-9-7 10:20
Michael_xpd 发表于 2013-9-7 10:16
new Test01()对象是在堆内存里;第二个testA是堆内存中对象new Test01()的testA;因为testA.testA指的是当前 ...

如果第二个testA是堆内存中的那就说明这个testA不是静态的,和我原对象里面的testA是静态的相矛盾啊

作者: Michael_xpd    时间: 2013-9-7 10:24
于XINCHENG 发表于 2013-9-7 10:20
如果第二个testA是堆内存中的那就说明这个testA不是静态的,和我原对象里面的testA是静态的相矛盾啊
...

对象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
陶智第 发表于 2013-9-7 10:24
第一个问题:
    静态方法都是放在方法区中,所以new Test01()对象是在方法区中
第二个问题:

static类型的对象被放在共享区,类中的方法区、共享区、数据区都在同一个区;


作者: 于XINCHENG    时间: 2013-9-7 10:45
陶智第 发表于 2013-9-7 10:24
第一个问题:
    静态方法都是放在方法区中,所以new Test01()对象是在方法区中
第二个问题:

如果testA在方法区中开辟了对象new Test01()的空间,testA.a = 2; 怎么能又在堆内存中再开辟一次空间,那testA.testA中的第二个testA是哪里来的?

作者: Bad_Boy    时间: 2013-9-7 11:29
于XINCHENG 发表于 2013-9-7 10:17
那请问,static Test01 testA = new Test01(); 的对象是开辟在哪个内存里了?
如果是在方法区中,那里面 ...

这是我理解的

无标题.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
  1. public class Test01 {
  2.         int a = 1;
  3.         static Test01 testA = new Test01(); //这句话会被编译器分解成两部

  4.       /*

  5.        static Test01 testA;

  6.        static{

  7.               testA=new Test01();

  8.        }

  9.       */
  10.         public static void main(String[] args) {
  11.                 testA.testA.a = 2;
  12.                 // TODO Auto-generated method stub
  13.                 testA.a = 1;
  14.                 System.out.println(testA == testA.testA); // 注意:此处的输出结果为true,为什么?
  15.   }
  16. }
复制代码
静态代码块的特点:随着类的加载而执行,并且只执行一次,优于主函数执行.
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。第二步是程序本身对静态变量初始化。这时会生成一个对象,并把地址赋值给引用变量,因为是静态的。所以到此已初始化完毕。以后在也不会在初始化。此时才会加载执行下面代码:

作者: 张文豪    时间: 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