java如何处理非静态变量?

java如何处理非静态变量?,java,oop,non-static,Java,Oop,Non Static,我在理解非静态变量的处理方式时遇到问题。我选择使用数组,这样就可以很容易地检索它的内存地址 考虑以下代码: public class tryClass { int[] v = {0}; // vector v is non-static (and NOT local to any method) tryClass obj; public void met () { obj = new tryClass(); obj.v[0] = 3

我在理解非静态变量的处理方式时遇到问题。我选择使用数组,这样就可以很容易地检索它的内存地址

考虑以下代码:

public class tryClass
{
    int[] v = {0}; // vector v is non-static (and NOT local to any method)
    tryClass obj;
    public void met ()
    {
        obj = new tryClass();
        obj.v[0] = 30;
        v[0]=3;
    }
    public static void main (String[] args)
    {
        tryClass obj = new tryClass(); // is this the SAME object as in met() ?
        int[] v = new int[1];
        obj.v[0] = 40;
        obj.met();
    }
}
为了了解每一步如何处理向量
v
,我在代码中填入了一些
println
指令,输出如下:

In main(), BEFORE running met()
    obj.v[0] = 40
    obj.v    = [I@78456a0c

INSIDE method met()
    obj.v[0] = 30
    v[0]     = 3
    obj.v    = [I@15357784
    v        = [I@78456a0c

In main(), AFTER running met()
    obj.v[0] = 3
    obj.v    = [I@78456a0c
我对许多事情感到非常困惑,首先是为什么在静态方法
main()
中调用
obj.v
的引用与在非静态方法
met()中调用
v
的引用相同。此外,在没有对象的情况下(当然是在非静态上下文中)调用时,
v
到底是什么

我是Java新手,我真的有无数的问题,我希望答案能完全解决它们。。。提前感谢你的帮助

为了完整起见,完整的代码是

public class tryClass
{
    int[] v = {0};
    tryClass obj;
    public void met ()
    {
        obj = new tryClass();
        obj.v[0] = 30;
        v[0]=3;
        System.out.println("\nINSIDE method met()");
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tv[0]     = "+v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        System.out.println("\tv        = "+v);
    }
    public static void main (String[] args)
    {
        tryClass obj = new tryClass();
        int[] v = new int[1];
        obj.v[0] = 40;
        System.out.println("In main(), BEFORE running met()");
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        obj.met();
        System.out.println("\nIn main(), AFTER running met()");
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
    }
}

为什么在静态方法main()中调用obj.v的引用与在非静态方法met()中调用v的引用相同

答:因为您没有将其重新分配给内存中的其他对象。它仍然指向内存中相同的“数组”对象,即使您在内部更改了数组的内容

查看您的代码,并附上我的评论:

public class tryClass
{
    // here, non-static variable v will be instantiated
    // as an array with a length of one, holding the value 0 in it's one slot;
    // it will be instantiated when an instance of tryClass is created.
    int[] v = {0};

    // here, this tryClass has another tryClass named "obj" in it as one of its fields.
    tryClass obj;

    public void met ()
    {
        // here, the tryClass's tryClass obj is instantiated
        // and this second tryClass's "v" is instantiated
        // and then it's one slot is set to 30.
        obj = new tryClass();
        obj.v[0] = 30;

        // now, the first tryClass's "v" is set to 3.
        v[0]=3;
    }

    public static void main (String[] args)
    {
        // creating a new tryClass.  This is NOT the same object as in met.
        // But it CONTAINS the same object in met.
        // You could call it by going obj.obj.
        tryClass obj = new tryClass(); // is this the SAME object as in met() ?  Answer: No.

        // this does nothing, it just creates another int[] v
        // that exists only inside the main() method.  It is not
        // the same as obj.v!
        int[] v = new int[1];

        // changing the contents of obj.v, but not reassigning obj.v itself.
        obj.v[0] = 40;

        // calling met, which will change obj.v's contents again, but not reassign it.
        obj.met();
    }
}

数组是可变的,这意味着即使它在内存中仍然是同一个对象,它的内容也可以更改。

您还应该打印出
obj
引用的值,当不是在静态上下文中时,
this
的值也可以打印出来。这将显示,您正在为
tryClass
类的不同实例打印
v
引用的值

public class tryClass
{
    int[] v = {0};
    tryClass obj;
    public void met ()
    {
        obj = new tryClass();
        obj.v[0] = 30;
        v[0]=3;
        System.out.println("\nINSIDE method met()");
        System.out.println("\tthis     = "+this); //add this
        System.out.println("\tobj      = "+obj);  //add this
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tv[0]     = "+v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        System.out.println("\tv        = "+v);
    }
    public static void main (String[] args)
    {
        tryClass obj = new tryClass();
        int[] v = new int[1];
        obj.v[0] = 40;
        System.out.println("In main(), BEFORE running met()");
        System.out.println("\tobj      = "+obj); //and this
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        obj.met();
        System.out.println("\nIn main(), AFTER running met()");
        System.out.println("\tobj      = "+obj); //and also this
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
    }
}
您还可以为该类创建构造函数:

public tryClass() {
    System.out.println("Creating new instance of tryClass!");
}
看看发生了什么


(或者,作为一种学习体验,您可以在IDE中查看调试器。这将非常有用……

当您执行静态main方法时,您要做的第一件事是创建tryClass的实例,并打印名为v的数组元素的值,v是该实例的一个属性。(obj.v[0])。
然后调用该实例的met方法,使该方法体中的非静态引用引用该实例的属性(您在main方法上创建的属性)。

您已经创建了tryClass的instanceof。因此,无论您打印的是Main方法还是class方法,您都打印的是来自“instance”obj的“array”引用,因此打印的是关于静态方法和类的相同referencerad,以及使用静态和实例字段时字段作用域的工作方式。这里有一个提示:尝试将您的(静态)“main”方法放在一个单独的类中(称为Start或其他什么),并让您的“tryClass”不受它的影响。这样一来,(静态)方法局部字段与(非静态)实例字段无关的原因就更清楚了:我还认为,提供一些您熟悉的其他语言的细节可能会帮助回答您的人。请注意,正如@ShivanDragon所说,非静态变量更确切地称为实例字段(同样适用于方法)。@ShivanDragon谢谢,我正在尝试你的建议。无论如何,我对编程语言不是很感兴趣,Java是我唯一“知道”的OOP。我只是有一个“公平的”了解Unix的Bash编程,但我认为这不会有任何帮助,是吗?非常感谢,非常感谢您的分步指导。但是您说的
//这里,这个tryClass有另一个tryClass,名为“obj”,这是什么意思我想我现在明白了:我创建了两个对象
obj
,第一个在
main()
方法中,第二个在
met()
中。调用
obj.met()
会使第二个
obj
成为一种“子对象”关于第一个,我应该通过
obj.obj
访问它。我说得对吗?第一个
obj
和第二个
obj
的顺序正确吗?@AndreasT是的,正确,我想你理解了。“子对象”是考虑它的一种方式,但在面向对象编程中,请根据HAS-A.tryClass HAS-A tryClass来考虑它。