Java类本身是否被视为对象?

5
我知道Java类为对象提供了蓝图。
我也知道所有的类都继承自Object类。
在这些事实的基础上,Java类本身是否仍然被认为是对象? 我搜索了许多资源,但仍感到困惑。许多参考资料都会说Java中的所有东西(除了原始数据类型)都是对象,包括类和您的类文件...例如这里:http://howtoprogramwithjava.com/podcast-episode-10-objects-and-static-keyword
我在StackExchange上搜索并发现这个问题有一定帮助,但并没有完全回答我的问题。

5
不,它们是不同的,但是每个类都有一个叫做Class对象的东西,比如Example.class。 - kosa
1
哇,你在这里提出的问题引起了真正的争论。 - Branislav Lazic
2
为什么要点赞一个重复的问题?这个问题已经被问了100次。 - raffian
6个回答

12

从语义上讲,类本身并不是对象,因为在类的执行过程中没有直接使用运行时对象。然而,其他对象存在,它们是类的表示,并且对它们在内存中进行的更改不会改变该类字节码的执行。然而,每个类都有一个关联的Class对象,允许通过反射与该类、其实例和成员进行交互。

事实上,这个类是通用的,因为 FooClass.class 实际上是 java.lang.Class<FooClass> ,这有助于泛型,在运行时传递 Class 对象可以解析泛型返回类型和约束。


3
不,反射使用类对象作为“粘合剂”或抽象层,将JVM中的类和环境隔离开来。 - nanofarad
此外,它无法执行任何操作 -- 不能添加或删除方法或字段,不能更改可见性等。 - yshavit
@Rogério,实际上不是这样的。 java.lang.instrument使用ClassDefinition来实现这一点。除了作为低级API或实际转换字节码的另一个对象的粘合剂之外,这里没有任何活跃修改类的方法此处,甚至没有本地方法。 - nanofarad
@hexafraction,我只是说“您可以在运行时更改字节码”,这是正确的。我没有说它是通过java.lang.Class中的方法完成的。如果您仍然认为Java类不是对象,则我认为您应该清楚而明确地指定您正在使用哪些客观标准。我无法想到任何特定要求,需要满足某些条件才能成为对象,而Class实例不能满足。 - Rogério
@Rogério,我这么认为是因为Class对象没有足够的信息来重建类,并加载/实例化/调用静态方法等。 - nanofarad
显示剩余2条评论

5

从概念上讲,类是状态和行为的描述。一个对象(实例)是包含该状态和行为的数据结构。

例如,给定一个类:

class User {
    String name;
    void setName(String name) {
        this.name = name
    }
}

User 具有行为和状态,即它有一个称为 nameField 和一个称为 setNameMethod。上述内容描述了这种行为。如果您创建一个实例

User user = new User();
user.setName("Jon");

现在你有一个包含实际状态和展示行为的数据结构。

在Java中,有一个叫做Reflection的东西,它基本上描述了类的元数据、它的状态和行为。这被解释为ClassFieldMethod类的实例。

在上面的例子中,由于字段name本身具有状态和行为(它有一个名称("name"),我们可以读取它或写入它),因此必须有一个描述它的类。描述该状态和行为的类是FieldField的实例包含状态和行为。

同样,Method类描述了一个方法。一个方法有一个状态,它的名字例如setName,它接受的参数例如String。它也有行为,例如它返回void(不返回任何内容)。

最后,您有一个名为Class的类,它描述了类的状态和行为。 Class的实例描述了类的状态和行为。例如,User类的Class实例将具有一个Field对象和一个Method对象(实际上它有更多,但请容忍)。字段和方法是类的状态。例如,行为是创建类的实例


2

编辑: 当类被调用时,它们也是对象。否则它们是引用类型。

对于每个类定义,类加载器会调用 java.lang.Class 的实例,并将这些特殊的 class 对象存储在 JVM 内存的 PermGen 空间中。

有关更多信息,请参见此处


1
是的,所有的类也都是对象。但这是错误的。请查看其他两个答案。 - Luiggi Mendoza
@LuiggiMendoza 其他的回答都是错误的。 - jtravaglini
这个网址是否足够:http://docs.oracle.com/javase/tutorial/reflect/class/index.html? - jtravaglini
2
因为有一个名为Class的Java类,它是java.lang.Class。你误解了它。 - Luiggi Mendoza
1
这里有一个区别:类是在编译时和运行时都存在的东西,而它关联的 Class 对象仅在运行时存在(就 Java 应用程序而言)。还有一个区别:如果你不修改代码两次运行同一个 Java 应用程序,你将使用相同的类,但它们会有不同的 Class 对象代表它们。 - yshavit
显示剩余8条评论

1
考虑到这些事实,Java类仍然被认为是对象本身吗?
不,你不能将Java类/类型称为对象/实例。
类型/类的对象意味着在堆上进行内存分配(其中内存取决于类内定义的成员变量)。当使用new关键字调用类型/类构造函数时,确实会发生这种情况。
然而,当一个类被JVM ClassLoader加载时,与该类关联或创建了一个Class(java.lang.Class)类/类型的对象。这个类对象对JVM有助于跟踪在JVM中运行的类,并且当同步静态方法时可以获取锁定。另一方面,类的Class对象对程序员也有很多帮助。
例如:反射(java.lang.reflect)...
就目前而言,Object(java.lang.Object)只是所有类的超类,这并不意味着类本身就是对象/实例。但如果有一个名为A的类,我们知道它本质上是java.lang.Object的子类,现在类A的任何对象/实例都将具有类A和java.lang.Object的属性。
底线:JVM内部的每个操作都会在面向对象原则(OOP)的影响下进行,因此有句话说“每件事情都是对象”,除了基本类型。如果有一个类被加载到JVM中而没有使用new关键字,它也将与java.lang.Class对象/实例相关联。

0

这应该更好地解释了; 例子简单地说,Car是一个类。但是我们可以根据它们的特征/属性拥有许多汽车对象帮助我们定义这些。因此,类不是对象。来自Oracle Docs.(由于某种原因,我们都与自行车相关联并且更容易理解,因此将自行车替换为汽车。)

在现实世界中,您经常会发现许多相同类型的个体对象。可能存在成千上万的其他汽车,全部都是同一品牌和型号。每辆自行车都是从相同的蓝图构建而成,因此包含相同的组件。用面向对象的术语来说,我们说您的自行车是称为自行车的对象类的实例。类是创建个体对象的蓝图。

以下Car类是自行车的一种可能实现:

class Car{

    int cadence = 0;
    int speed = 0;
    int gear = 1;

    void changeCadence(int newValue) {
         cadence = newValue;
    }

    void changeGear(int newValue) {
         gear = newValue;
    }

    void speedUp(int increment) {
         speed = speed + increment;   
    }

    void applyBrakes(int decrement) {
         speed = speed - decrement;
    }

    void printStates() {
         System.out.println("cadence:" +
             cadence + " speed:" + 
             speed + " gear:" + gear);
    }
}

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接