我现在已经学习Java编程两年了,但我遇到了一个问题,我无法理解和区分类、引用和对象。
我不确定类或引用是否相同,尽管我对对象有些了解。
有人能够完整地区分一下类、引用和对象吗?
我所知道的是,类更像是对象的模板(就像房屋的蓝图是类,而房子则是对象)。
我现在已经学习Java编程两年了,但我遇到了一个问题,我无法理解和区分类、引用和对象。
我不确定类或引用是否相同,尽管我对对象有些了解。
有人能够完整地区分一下类、引用和对象吗?
我所知道的是,类更像是对象的模板(就像房屋的蓝图是类,而房子则是对象)。
如果你喜欢房屋比喻:
你可以随意复制这个引用,但只有一个房子 -- 你复制的只是写有地址的卡片,而不是房子本身。
在Java中,你不能直接访问对象,只能使用引用。Java不会复制或者分配对象给其他对象。但是你可以复制和赋值引用到变量,使它们指向同一个对象。Java方法总是按值传递,但是这个值可以是一个对象的引用。因此,如果我有:
Foo myFoo = new Foo(); // 1
callBar(myFoo); // 2
myFoo.doSomething() // 4
void callBar(Foo foo) {
foo = new Foo(); // 3
}
接下来我们来看一下发生了什么。
new Foo()
告诉 JVM 使用 Foo
蓝图来建造一个新房子。JVM 这样做,并返回房子的引用。您然后将此引用复制到 myFoo
中。这基本上就像要求承包商为您建造一座房子。他建造了房子,然后告诉您房子的地址;您会将该地址写下来。callBar
。让我们接下来跳转到该方法。Foo foo
。Java 是传值调用的,因此 callBar
中的 foo
是 myFoo
引用的 副本。将其视为给 callBar
一张带有房子地址的卡片。那么 callBar
会如何使用这张卡呢?它要求建造一个新房子,然后使用您提供的卡片来写入该新房子的地址。请注意,现在的 callBar
无法访问第一个房子(我们在第1行中建造的那个房子),但该房子并不会因为曾经带有其地址的卡片现在带有其他房子的地址而发生变化。myFoo
来调用它的一个方法(doSomething()
)。这就像查看卡片,在上面写有地址的房子中做某些事情。请注意,callBar
方法不会更改带有 myFoo
地址的卡片 -- 记住,我们给了 callBar
我们引用的 副本。整个序列可能类似于:
myFoo
的卡片中。callBar
。在此之前,我们将写在 myfoo
上的地址复制到一张新卡片上,然后将它交给 callBar
。它称该卡片为 foo
。callBar
要求 JVM 建造另一座房子。它创建了一个新房子,并返回新房子的地址。 callBar
将此地址复制到我们给它的卡片中。int
之间的区别一样 - 整数(或地址)是您想要存储的东西,而int
(或引用)是存储它的东西。 - yshavitCar
对象的地址,它只是可以存储地址副本的地方。如果你修改了引用,那么并不会改变 Car
的地址——这只是意味着你现在指向了另一个对象(或者是 null
,也就是没有地址)。 - yshavitString s;
但是在这里,你仅仅创建了一个引用,而不是一个对象。如果此时决定向 s
发送消息,将会出现错误,因为它实际上没有绑定到任何内容(没有电视)。因此更安全的做法是,在创建引用时总是进行初始化:
String s = "asdf";
然而,这里使用了一种特殊的Java功能:可以用引号括起来的文本初始化字符串。通常,您必须为对象使用更一般类型的初始化。
当您创建引用时,您希望将其连接到一个新对象。通常情况下,您需要使用new运算符。关键字new表示:“给我一个新的这个对象。”因此,在前面的示例中,您可以这样说:
String s = new String("asdf");
这不仅意味着“创建一个新的字符串”,而且通过提供初始字符字符串来提供有关如何创建字符串的信息。 当然,除了字符串之外,Java还配备了大量现成的类型。更重要的是,您可以创建自己的类型。实际上,在Java编程中创建新类型是基本活动。
假设你在那里写了两行代码:
Engine app1 = new Engine(); //LINE 1
Engine app2 = app1; //LINE 2
类: 结构或蓝图
对象: 物理表现
引用: 对象地址
========= 类和对象 ===========
类 => 例如:人(更像是想象)
对象 => 例如:约翰,迈克(真实的人)
=========== 引用 ============
例如:
Television tv1; - (电视是一个类,tv1是没有电视的遥控器)
Television tv2 = new Television(); - (现在tv2遥控器有了一台电视)
tv1 = tv2; - (现在tv1和tv2可以控制同一台电视)
Television tv3 = new Television(); - (tv3是一个新的遥控器,带有新的电视)
Object
是 Class
定义的运行时表示,而您使用对象的名称称为 reference
(因为它引用了内存中实际对象的位置)
例子:
MyClass ref = new MyClass();
这里,MyClass 是(包含)类的定义。
new MyClass() 创建了该类的一个对象(仅在执行期间完成,因此是运行时表示)
ref 是您用于处理类对象的名称,是引用。
类(Class):用于将现实生活中的实体定义到编程环境中。
任何具有至少一个属性和相应行为的现实生活实体都可以被视为一个类。让我们以汽车为例,它具有一个名为“加速器”(accelerator)的属性,帮助汽车移动并控制其速度。相应的行为是“加速”(acceleration),它与施加给加速器的推力成正比。
class Car {
private String tier;
private String tierFriction;
private double weight;
private double gasFedToEngine;
}
类中的方法
)始终取决于属性(类的全局属性
)。现在,如果您想要更多详细信息,可以将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;
}
对象:用于定义实体的各种类型,并对它们进行单独的数据操作。
现在我们已经为程序定义了一个实体,比如说我们拥有一个二手车展厅,里面有不同公司的汽车。因此每辆汽车都成为我们实体的一个对象
。对象可以是奥迪、日产、法拉利等。所以在开业后,我们可以像这样向展厅添加汽车:
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 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).
**/
}
}
类是一个模板,你说得对。它是关于数据结构的一些知识。对象是内存中的结构实例。引用是该实例的内存地址。
如果你所说的对象
是指Java标识符,那么Object
是所有复杂Java类的基本类。