2013-04-20 90 views
3

我读过一堂课是创建对象的模型,并且实际上不存在而对象是真实的。但是我们在一个类中创建变量,甚至操纵它们。当班级不真实时,班级内部是如何创建变量的?

  1. 这个类在物理上不存在时怎么可能?

  2. 什么时候为这些变量创建了内存?

  3. 为这些变量创建的内存在哪里?

+0

在静态变量的情况下,请参阅海德的答案。在实例变量的情况下,以及...向new'运算符(关键字)问好,这将触发实际的分配。 – datenwolf 2013-04-20 10:25:34

+1

你读的是错的。对于已经在Java中加载的每个类确实有一个Class对象。在C++等其他语言中,类的“现实”在编译代码的字节中,除了创建对象的指令外,还可能存在表示静态变量的“静态”存储位置。 – 2013-04-20 11:49:57

回答

3

如果你的意思是静态类变量,它们quaranteed被initualized和内部类的任何静态初始化代码quaranteed要运行,使用前级。到底什么时候,没有指定IIRC,不同的JVM可能会在不同的时间这样做。它们与具有这些语言的语言中的全局变量基本相同。

所以要重申:静态的东西存在并在第一次使用之前被初始化。 JVM实现会照顾到这一点。

但有一个对象:类对象的实例,它是class Class的子类。


增加:事实上,在Java类存在,所以具体而言,它们可以被序列化,转移通过网络到不同的JVM,反序列化在那里,产生在那里的类和代码执行的对象。简单的例子就是在浏览器中运行的香草Java小程序。另一个例子是Jenkins/Hudson CI系统中的从属节点,其中从属程序非常小,只包含接收,反序列化和实例化这些类的类和对象的代码,由它们连接的主服务器发送。

+0

非常感谢你 – user2301829 2013-04-29 13:26:53

3

试着用这种方式思考它。这并不是对Java运行时如何完成这个任务的精确解释,而是一种思考类/对象二元性的方法,可以帮助您。

当您编写一个类X时,您将描述代码和数据。运行时只需要一些东西的副本 - 例如代码和静态变量 - 以及其他事物的每个对象一个副本,如实例变量。你在你写的类文件中描述了这两件事,尽管它们将被单独存储。

将每个类的一次拷贝看作全部存储在一块内存中 - 它将被称为C中的一个结构。在Java中,第一次在程序中引用类X运行时分配此块内存并将其与类X关联。

当程序执行诸如“X x1 = new X()”之类的语句时,运行时会分配另一个包含内存(或结构)的块,其中包含所有的实例变量,并保持一个单独的指针,以指向与x1变量相关联的指针。

现在,当程序执行类似“Arc arc = x1.getArc();”时,运行时使用第一个指针引用方法getArc()中的代码,第二个指针引用实例变量与x1关联,并使用这些实例变量执行指示的代码。

OO编程提供了将数据与操作它的代码关联的方式,使我们能够将程序组织为组合代码和数据的“对象”。运行时间为我们追踪事物的不同副本。

我认为说这个类不存在是不准确的,它只是不会以你写它的形式存在。

0

类在运行时在JVM中物理存在。您阅读的解释是试图劳动点A,而稍后留下其余细节。学校和书籍一直都在这样做。

在Oracle JVM类中,从加载它们的那一刻开始就有物理表示。事实上,每个对象都有一个指向该类的指针,许多对象可以指向同一个类。

0

我不会想到一个类或物体作为物理的东西,这似乎让我感到困惑。一个类通常被描述为一个对象的蓝图。对象必须使用new关键字实例化(创建),当实例化对象时,对象的类将用作创建基本默认对象的蓝图。然后,即使在运行时,也可以通过引用内存中存储它的位置并使用对象的类中的方法来操作对象的类中的字段来操作该对象,至少这是它通常应该完成的方式,它的所谓的封装,在OOP中非常重要,所以如果你对封装不熟悉,我会建议研究它。

我提到一个对象可以在运行时进行操作,这是对象和类之间的主要区别。类可以使用称为反射的东西,但这是另一天的另一个话题。变量或字段有时被描述为地址,它是对存储对象的内存位置的引用。对象不被直接访问,它们通过变量被引用。

JLabel label; 

上述代码在内存留出的位置来存储一个JLabel对象时其与new关键字实例化。到目前为止,还没有创建对象,我们已经声明了一个变量,它是对内存中位置的引用,当创建对象时,它将被存储。我们不会直接访问我们的JLabel对象,我们将使用我们创建的'label'变量来引用内存中的实际对象。所以,如果我们创建了两个JLabel对象和实例化它们,像这样...

JLabel label; 
label = new JLabel(); 
JLabel anotherLabel = new JLabel("this is another label"); 

我们现在有两个JLabel的对象。第一个对象首先声明一个变量来引用该对象,然后在一个单独的行上实例化它。第二个对象声明对它的引用并将它全部在一行中实例化。您既可以创建对象,也可以使用这两种方法有不同的原因。当一个对象被创建时,至少有一个构造函数被调用,第一个对象调用不带参数的JLabel类中的构造函数;第二个对象使用JLabel类,需要一个String,并创建显示在传递给构造函数的文本对象内部的构造。

现在想象的程序正在运行,我们要改变的第一个对象,因此会显示一些文本,因为它目前是空白,因为我们使用的是不带任何参数的构造。我们可以使用像这样的setText(String)方法来操纵对象。

label.setText("now the first label displays text"); 

我们没有用这种方法改变了JLabel类以任何方式,但我们已经改变了对象,因此现在显示的文字。我可能会因为这个答案而失去一大堆声望点或者其他任何东西,因为我可能没有完全正确地解释每一个细节,但我回答了这个问题,因为你问了一些对我来说很困难的问题理解了很长时间,可能比大多数更多,因为我从来没有参加过编程课。有很多这样的东西,我不可能在没有写书的情况下完全解释它,所以我没有进入范围,访问修饰符,静态等东西,但我试图涵盖我认为重要的东西来理解你是什么问。就像我说的,我没有接受过正规教育,所以请就我的价值做出回答,但希望我能够让它更容易理解。

哦,我忘了你的其他问题。在创建对象的变量时声明内存中用于存储对象的位置。此时有一个位置,但内存中的大小仍为0或为空,因为没有对象。实际存储对象所需的内存将在对象实例化时填充。