【问题标题】:What are classes, references and objects?什么是类、引用和对象?
【发布时间】:2012-03-02 17:30:45
【问题描述】:

我已经编写 java 2 年了,显然我遇到了一个问题,我无法再次理解和区分类、引用和对象(我不明白为什么我忘记了这些概念)。

让我们来解决这个问题,即我不确定类或引用是否相同,尽管我已经知道什么是对象。

有人能以一种很好、易于理解和完整的方式区分什么是类、引用和对象吗?

我所知道的是,这个类更像是一个对象的模板(房子的蓝图,其中类是蓝图,房子是一个对象)。

【问题讨论】:

  • 再次学习基础知识。它永远不会太晚..:)
  • 如果您有 C 经验(或某些过程语言),您可以将对象视为带有方法的结构。所以 class 将是 de struct 声明(带有关联的方法), objects 将是给出的具体结构(这个结构是一个对象,那个结构是另一个对象)和 references 是指向该结构的指针。

标签: java oop class object reference


【解决方案1】:

当你编写代码时,你构建了一个

实例(出现、复制)

一个

对象

一个说

并保留一个

参考

到它,所以你可以调用它的方法。

此外,还有一些OOP 基础知识:ClassesObjectInstanceReference

【讨论】:

  • “保留”参考是什么意思?它就像那个对象的实现吗?还是对象是实现本身?
  • @user962206 引用只不过是指向内存中所述对象所在位置的“指针”。有人可能会说您在 Class 文件中编写了“实现”,不确定您的意思是什么?
  • 这就是我的意思,但如果可以的话,你能向我解释更多关于参考的细节吗?我确实得到了对象和类,但没有得到参考
  • 好的,谢谢,我现在终于明白了 :)! Car myCar = new Car() myCare 是参考吧?
  • @Marcelo Slight nitpick:引用不是Car 对象的地址,它是您可以存储地址副本的地方。如果您修改引用,它不会更改 Car 的地址 - 只是意味着您现在指向不同的对象(或 null,它不是地址)。
【解决方案2】:

类是一个模板,你是对的。这是关于数据结构的一些知识。对象是内存中的结构实例。引用是该实例的内存地址。

如果Object 指的是java 标识符,那么Object 是所有复杂Java 类的基本类。

【讨论】:

    【解决方案3】:

    假设你写了两行代码:

    Engine app1 = new Engine(); //LINE 1
    
    Engine app2  = app1; //LINE 2
    

    在第 1 行中,Engine 是一个,它基本上是一个蓝图。

    new Engine() 是在堆上创建的实例

    您通过在代码中使用 app1 和 app2 来引用该实例

    所以 app1 和 app2 是 引用

    【讨论】:

    • 如果你是说实例,你是说对象?
    • 所以 app2 不包含在第 1 行创建的引擎的副本,它包含指向引擎的引用的副本。
    • 当对引擎的引用返回 null 或未指向任何内容时,也会引发 Null 指针异常。
    【解决方案4】:

    当您创建一个对象时,幕后发生的事情是为包含该对象保留一块内存。这可能是伟大的大记忆景观中的任何地方;这取决于操作系统和编译器,您对它最终的位置没有任何控制或知识。

    那么问问你自己,如果你不知道它在内存中的什么位置,你如何使用它?如果您不知道该值的存储位置,如何从中读取值?这就是参考为您做的事情。它们是与物体保持联系的一种方式。这是一个附在气球上的小绳子,作为参考。

    您使用引用表示“我现在想触摸 this 对象!”或“我想从 this 对象中读取值!”。

    【讨论】:

      【解决方案5】:

      如果你喜欢住房隐喻:

      • 就像房子的蓝图。使用此蓝图,您可以建造任意数量的房屋。
      • 您建造(或用 OO 术语实例化)的每个房屋都是一个对象,也称为实例
      • 当然,每个房子也有一个地址。如果你想告诉某人房子在哪里,你会给他们一张写有地址的卡片。该卡片是对象的reference
      • 如果您想参观房子,请查看卡片上写的地址。这称为取消引用

      您可以随意复制该参考资料,但只有一所房子——您只是复制上面有地址的卡片,而不是房子本身。

      在Java中,你不能直接访问对象,你只能使用引用。 Java 不会相互复制或分配对象。但是您可以复制和分配对变量的引用,以便它们引用同一个对象。 Java 方法总是按值传递,但值可以是对象的引用。所以,如果我有:

      Foo myFoo = new Foo();     // 1
      callBar(myFoo);            // 2
      myFoo.doSomething()        // 4
      
      void callBar(Foo foo) {
          foo = new Foo();       // 3
      }
      

      那么让我们看看发生了什么。

      1. 第 1 行发生了几件事。new Foo() 告诉 JVM 使用 Foo 蓝图构建新房子。 JVM 这样做,并返回对房子的引用。然后将此引用复制到myFoo。这基本上就像要求承包商为您建造房屋一样。他做了,然后告诉你房子的地址;你把这个地址写下来。
      2. 在第 2 行中,将此地址提供给另一个方法 callBar。接下来让我们跳到那个方法。
      3. 在这里,我们有一个参考Foo foo。 Java 是按值传递的,因此callBar 中的foomyFoo 引用的副本。可以把它想象成给callBar 自己的卡片,上面有房子的地址。 callBar 用这张卡做什么?它要求建造一座新房子,然后用你给它的卡片写下新房子的地址。请注意,callBar 现在无法到达第一个房子(我们在第 1 行中建造的那个),但该房子并没有改变,因为曾经有它的地址的卡现在有其他房子的地址就可以了。
      4. 回到第一个方法,我们取消引用 myFoo 以调用它的方法 (doSomething())。这就像看卡,去卡上地址的房子,然后在那房子里做点什么。请注意,callBar 方法不会更改带有 myFoo 的地址的卡 - 请记住,我们给 callBar 提供了我们参考的副本

      整个序列会是这样的:

      1. 让JVM盖房子。确实如此,并给了我们地址。我们将此地址复制到名为 myFoo 的卡中。
      2. 我们调用callBar。在此之前,我们将写在myfoo 上的地址复制到一张新卡上,然后将其提供给callBar。它称那张卡为foo
      3. callBar 向 JVM 请求另一个房子。它创建它,并返回新房子的地址。 callBar 将此地址复制到我们提供给它的卡上。
      4. 回到第一种方法,我们查看原始的未更改的卡片;去我们卡上地址的房子;并在那里做点什么。

      【讨论】:

      • 最后一个问题基本如此。 myFoo 是您存储所述对象的引用的位置?
      • @user962206 不客气。 :) 至于您的问题,基本上:在口语中, myFoo is 是引用,它是您存储对象的 address 的位置。 (顺便说一句,你永远不会真正看到那个地址在 Java 中是什么——你只知道它在那里,并且 JVM 知道如何查看它。)如果你阅读 JLS,他们会说 myFoo 是一个变量引用类型,并且它存储对对象的引用。
      • @iamcreasy 他们非常相似。地址是对象所在的 JVM(即内存)中的位置。引用是指向该地址的变量。类比就像问整数和int 之间的区别是什么——整数(或地址)是您想要存储的东西,而int(或引用)是存储它的东西。跨度>
      • @BKSpureon Callbar 没有得到房子,而是得到了一张写有房子地址的卡片。所以,它没有在那个地址建新房子——它建了一个新房子,然后在卡片上写了那个房子的地址。这意味着 Callbar 再也找不到旧房子了——但没有其他人受到影响。老房子还在,任何有老房子地址的其他卡片的人都可以找到它。
      • @BKSpureon,Java 方法总是按值传递(对象引用)。所以当 callBar(myFoo);仅调用值(引用)被传递,并且“foo”的范围仅在 callBar 内。并且 foo 仅获得 new Foo() 。所以 foo 正在引用新的 - 我想我是对的。
      【解决方案6】:

      ObjectClassdefinition 的运行时表示。 您使用对象的名称称为reference(因为它引用了内存中的实际对象位置)

      例子

      MyClass ref = new MyClass();
      

      这里,MyClass 是(包含)class 定义。

      new MyClass() 为此类创建一个对象(仅在执行期间完成,因此是运行时表示)

      ref 是您用于处理类对象的名称,是reference

      【讨论】:

        【解决方案7】:

        ========= 类和对象 ===========

        类 => 例如:人(更像是想象)

        对象 => 例如:约翰、迈克(真人)

        ===========参考=============

        例如:

        Television tv1; - (Television 是一个类,tv1 是没有Television 的遥控器)

        Television tv2 = new Television(); - (现在 tv2 遥控器有电视)

        tv1 = tv2; - (现在tv1和tv2可以控制同一个电视)

        Television tv3 = new Television(); - (tv3 是带有新电视的新遥控器)

        【讨论】:

          【解决方案8】:

          在 Bruce Eckel 的“Thinking in Java”一书中对其进行了完美的描述:

          “你可以想象一台电视机(对象)和一个遥控器(参考)。只要你拿着这个参考,你就可以连接到电视,但是当有人说,“换个频道”或“降低音量”,您正在操作的是参考,这反过来会修改对象。如果您想在房间内移动并仍然控制电视,请随身携带遥控器/参考,而不是电视。

          此外,遥控器可以独立使用,无需电视。也就是说,仅仅因为你有一个引用并不意味着一定有一个对象连接到它。所以如果你想保存一个单词或句子,你可以创建一个字符串引用:

          String s;
          

          但是在这里你只创建了引用,而不是对象。如果此时您决定向 s 发送消息,则会收到错误消息,因为 s 实际上并没有附加到任何东西(没有电视)。因此,更安全的做法是始终在创建引用时对其进行初始化:

          String s = "asdf";
          

          然而,这使用了一个特殊的 Java 特性:字符串可以用带引号的文本来初始化。通常,您必须对对象使用更通用的初始化类型。

          当您创建一个引用时,您希望将它与一个新对象连接起来。通常,您使用 new 运算符执行此操作。关键字 new 说:“让我成为这些对象中的一个新对象。”所以在前面的例子中,你可以说:

          String s = new String("asdf");
          

          这不仅意味着“为我创建一个新字符串”,而且还提供了有关如何通过提供初始字符串来创建字符串的信息。 当然,除了 String 之外,Java 还带有大量现成的类型。更重要的是您可以创建自己的类型。事实上,创建新类型是 Java 编程的基本活动。”

          【讨论】:

            【解决方案9】:

            类:用于将现实生活中的实体定义到编程环境中。

            任何具有至少一个property 和一个对应的behaviour 的现实生活中的实体都可以被视为一个类。让我们举一个汽车的例子,它有一个属性accelerator,它可以帮助汽车移动并控制它的速度。对应的行为是acceleration,它与应用于加速器的推动成正比。

            class Car {
                private String tier;
                private String tierFriction;
                private double weight;
                private double gasFedToEngine;
            }
            

            上面的类显示了 Car 的一些属性,它的加速度取决于这些属性。行为 (method in the class) 始终取决于属性 (global attribute(s) of the class)。现在,如果您想了解更多详细信息,可以将 Tier 定义为另一个实体,那么定义将如下所示

            class Tier {
                private String tierMaterial;
                private String tierFriction;
                private double weight;
                private double tierDiameter;
            }
            
            class Car {
                private Tier tier;  // getting all properties of Tier here itself
                private double weight;
                private double gasFedToEngine;
            }
            

            对象:用于定义实体的各种风格并分别对它们执行数据操作。

            现在我们已经为我们的程序定义了一个实体,比如说我们有一个二手车陈列室,有不同公司的汽车。所以每辆车都成为我们实体的object。对象可以是奥迪、日产、法拉利等。所以在打开陈列室后,我们像这样添加汽车

            static List<Car> showroomCars = new ArrayList<Car>();
            public boolean addCarToShowroom() {
                Car carNissan = new Car();  // always creates a new objects and allocates some memory in heap
                carNissan.setName("Nissan");
                carNissan.setColor(RED);
                carNissan.setWeight(300);
                showroomCars.add(carNissan);
            
                Car carAudi = new Car();
                carAudi.setName("Audi");
                carAudi.setColor(BLACK);
                carAudi.setWeight(270);
                showroomCars.add(carAudi);
            }
            

            因此,现在陈列室中添加了两款新车,一款是日产,另一款是奥迪,每款都有自己的特定属性值。

            Class 只给出定义,在Object 上进行操作,对于任何类进行操作,都应该创建对象。每次为类创建一个对象时,其所有非静态(实例)变量都将以其各自的默认值加载到内存中。

            引用:用于寻址对象

            当我们说Car carAudi = new Car(); 时,我们为 Car 定义了一个新对象,并为该对象分配了一个内存位置。引用变量carAudi 保存了该对象的内存地址。用户永远不会直接访问对象,也不会直接访问它的内存位置。这就是引用变量的意义所在,它存储hexadecimal 格式的内存位置。如果我们想对对象进行修改,请不要直接借助引用。

            一个对象可以有任意数量的引用,但一个引用一次只能指向一个对象。

            class Car {
                void test() {
                    Car car1 = new Car();  // (1)
                    Car car2 = new Car();  // (2)
                    car2 = car1;
                    /** 
                     Says that car2 should point to where car1 points, so now both points to first object of Car
                     But for this car2 has to loose its current object-(2), making it an Abandoned object (An object with no active reference from the stack).
                    **/
                }
            }
            

            【讨论】:

              【解决方案10】:

              班级: 结构或蓝图

              对象: 物理表现

              参考: 对象地址

              【讨论】:

                【解决方案11】:
                • 在现实世界中,对象是在这个宇宙中可以看到和触摸的物质事物。
                • 在编程中,对象是相同的,但它们被存储或捕获在内存中,就像创建任何对象时一样。它将在 RAM(内存)中创建。因此,作为人类,我们将无法看到或触摸它,但它确实存在于记忆中的某个地方。
                • 因此,我们不关心系统如何创建或销毁对象,而是看看如何使用编程来处理它。
                • 为了创建对象,编程语言提供了我们可以使用的语法格式来处理这些对象。
                • 现在,如果您想创建一辆定制的新车,那么您将如何定义您想要创建的对象,然后您必须向制造商提供您的要求,对吗?。
                • 编程方式相同,使用类。该类是一个蓝图,它将定义对象的外观/它将存储的所有数据以及它将执行的所有操作。它不存在于内存中,仅用于定义创建对象的要求。

                我们以学生为例:

                //We have a Student class. Below are some attributes which we will use:
                    class Student
                    {
                        string Name;
                        int Age;
                        string Address;
                    }
                

                现在,Above Student 并不存在。这只是学生将如何的蓝图。如果我们需要创建一个学生,那么我们称之为创建一个对象,下面是创建一个学生的格式。

                Student student=new Student();
                

                现在,已经在内存中创建了 1 个学生对象,可用于设置任何姓名/年龄/地址并获得相同的信息,如下所示:

                        static void Main(string[] args)
                        {
                            Student student = new Student();
                            student.Name = "Vivek";
                            student.Age = 24;
                            student.Address = "Address";
                            Console.Write("Student Name is " + student.Name + " whose age is " + student.Age + " and he/she stays at " + student.Address);
                        }
                

                现在,假设你想为学生提供一些工作,你会怎么做?

                //By writing a function/method and write the code which student should handle as below:
                    class Student
                    {
                        public string Name;
                        public int Age;
                        public string Address;
                
                        public void Run()
                        {
                            //Write some code
                        }
                
                        public void Walk()
                        {
                            //Write some code
                        }
                    }
                

                以上只是一个示例,因为学生不会在内存中运行,因此,您必须编写的代码仅是 C# 代码或您用于编写代码的任何编程语言。就像用 C# 做一些操作一样。

                现在,我想强调一点:

                • 如果您在现实世界中看到。学生不仅包含姓名/地址/年龄,而且学生还具有其他属性,例如母亲姓名/父亲姓名/护照等。除了正常属性外,我们还可以添加身体部位,例如大脑/心脏/腿等。
                • 因此,如果您将所有属性添加到 Class Student,它可能会更复杂。

                示例:您的定制汽车不会定制汽车的所有部件。您必须使用现有的部件,如轮子/层/空调等。因此,类可以使用现有的类/结构/方法/字段等来满足要求。正如您在下面看到的那样,该类正在使用其他类/结构/方法/字段等来满足要求:

                        //String is also class which represents text as a sequence of UTF-16 code units
                        public string Name;
                
                        //Integer is a struct which represents a 32-bit signed integer
                        public int Age;
                
                        //String is also class which represents text as a sequence of UTF-16 code units
                        public string Address;
                

                【讨论】:

                  【解决方案12】:

                  Java 中的一切都与类对象和类相关联,包括属性和方法。例如:汽车是现实生活中的物体。汽车具有属性,例如重量和颜色,以及方法,例如驱动和制动。类就像一个对象构造函数或创建对象的“蓝图”。

                  引用是指示对象变量和方法存储位置的地址。当您将对象分配给变量或将对象作为参数传递给方法时,您实际上并没有使用对象。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-05-31
                    • 2011-05-26
                    • 1970-01-01
                    • 2021-07-20
                    相关资源
                    最近更新 更多