【问题标题】:what is the Class object (java.lang.Class)?什么是类对象(java.lang.Class)?
【发布时间】:2011-05-26 02:21:28
【问题描述】:

Class 的 Java 文档说:

Class 对象由 Java 虚拟机在加载类时自动构造,并通过调用类加载器中的 defineClass 方法。

这些Class 对象是什么?它们是否与通过调用 new 从类实例化的对象相同?

另外,例如object.getClass().getName(),即使我不继承自java.lang.Class,如何才能将所有内容类型转换为超类Class

【问题讨论】:

    标签: java class inheritance


    【解决方案1】:

    我还想在 ColinD 的回答中添加 getClass 将为相同类型的实例返回 same object。这将打印 true:

        MyOtherClass foo = new MyOtherClass();
        MyOtherClass bar = new MyOtherClass();
        System.out.println(foo.getClass()==bar.getClass());
    

    注意不是equals,我用的是==

    【讨论】:

      【解决方案2】:

      类对象是一种描述对象类的元对象。它主要与 Java 的反射功能一起使用。您可以将其视为实际课程的“蓝图”。例如。你有一个像这样的汽车类:

      public class Car {
          public String brand;
      }
      

      然后您可以构造一个描述您的“汽车”类的 Class 对象。

      Class myCarClass = Class.forName("Car");
      

      现在您可以对该 Class 对象上的 Car 类进行各种查询:

      myCarClass.getName() - returns "Car"
      myCarClass.getDeclaredField("brand") - returns a Field object describing the "brand" field
      

      等等。每个 java 对象都有一个方法 getClass(),它返回描述 Java 对象的 Class 的 Class 对象。所以你可以这样做:

      Car myCar = new Car();
      Class myCarClass  = myCar.getClass();
      

      这也适用于你不知道的物体,例如你从外面得到的物体:

      public void tellMeWhatThisObjectsClassIs(Object obj) {
          System.out.println(obj.getClass().getName());
      }
      

      你可以给这个方法提供任何 java 对象,它会打印你给它的对象的实际类。

      使用 Java 时,大多数时候您无需担心 Class 对象。不过,他们有一些方便的用例。例如。它们允许您以编程方式实例化某个类的对象,该类通常用于对象序列化和反序列化(例如,将 Java 对象来回转换为 XML 或 JSON)。

      Class myCarClass = Class.forName("Car");
      Car myCar = myCarClass.newInstance();  // is roughly equivalent to = new Car();
      

      您还可以使用它来找出类的所有声明的字段或方法等,这在某些情况下非常有用。所以例如如果你的方法得到了一个未知的对象并且你需要了解更多关于它的信息,比如它是否实现了一些接口等,Class 类是你的朋友。

      长话短说,java.lang.reflect 包中的 Class、Field、Method 等类允许您分析定义的类、方法、字段,创建它们的新实例,调用各种方法其他东西,它们允许您在运行时动态地执行此操作。

      【讨论】:

      • 类 c1 = Car.class;这个“类”是什么?它是存在于每个类中的公共变量吗?
      • 它基本上是语法糖。它是编译器评估为加载具有给定名称的类对象的东西。大致相当于 Class.forName("fully qualified class name") 但在编译时检查该类是否存在,而 Class.forName() 在运行时执行。
      【解决方案3】:

      没有任何东西被类型转换为Class。 Java 中的每个Object 都属于某个class。这就是为什么被所有其他类继承的Object 类定义了getClass() 方法。

      getClass(),或类文字 - Foo.class 返回一个 Class 对象,其中包含有关该类的一些元数据:

      • 姓名
      • 方法
      • 字段
      • 构造函数
      • 注释

      还有一些有用的方法,比如强制转换和各种检查(isAbstract()isPrimitive() 等)。 the javadoc 准确显示了您可以获得的有关课程的信息。

      因此,例如,如果为您的方法提供了一个对象,并且您想要处理它以防它被 @Processable 注释注释,那么:

      public void process(Object obj) {
          if (obj.getClass().isAnnotationPresent(Processable.class)) {
             // process somehow; 
          }
      }
      

      在此示例中,您获取有关给定对象的类的元数据(无论它是什么),并检查它是否具有给定的注释。 Class 实例上的许多方法称为“反射操作”,或简称为“反射”。Read here 关于反射、为什么以及何时使用它。

      另请注意,Class 对象表示枚举和接口以及正在运行的 Java 应用程序中的类,并具有各自的元数据。

      总而言之 - java 中的每个对象都有(属于)一个类,并且有一个相应的 Class 对象,其中包含有关它的元数据,可以在运行时访问。

      【讨论】:

      • 进一步思考这个问题很有趣。 Class 类继承自 Object 本身。 Class.class 返回一个代表Class 类的Class 对象。你可以反思反思。我的头飞溅。
      • @pst:我有。这让我想伤害别人。任何在其根类型上具有this many 方法的语言/框架都应该被埋葬。它具有 PHP 风格的 tack-random-crap-onto-the-API-without-any-forethought 综合症。提示火焰......
      • 类 c1 = Car.class;这个“类”是什么?它是存在于每个类中的公共变量吗?
      • 在某种程度上,是的。事实上,它是一个“类字面量”——这就是您通过名称引用 Class 对象的方式。
      • @cdhowie 你的评论在语义上满足了我的“类”这个词。
      【解决方案4】:

      为了完全理解类对象,让我们回过头来理解我们首先得到了类对象。你看,你创建的每一个.java文件,当你编译那个.java文件时,jvm会创建一个.class文件,这个文件包含了类的所有信息,即:

      1. 类的完全限定名
      2. 班级家长
      3. 方法信息
      4. 变量字段
      5. 构造函数
      6. 修饰符信息
      7. 常量池

      您在上面看到的列表是您通常在典型课程中看到的列表。现在,到目前为止,您的硬盘上存在您的.java 文件和.class 文件,当您实际需要使用该类时,即在main() 方法中执行代码时,jvm 将使用该.class 文件在您的硬盘驱动器中并将其加载到 jvm 中的 5 个内存区域之一,即方法区域,在将 .class 文件加载到方法区域后,jvm 将立即使用该信息和一个 表示的类对象 存在于堆内存区域中的那个类。

      这是顶层视图,

      .java --compile--> .class -->当你执行你的脚本时--> .class加载到方法区--jvm从方法区创建类对象-->一个类对象诞生了

      使用类对象,您可以获得类名、方法名等信息,以及有关该类的所有信息。

      还要记住,您在脚本中使用的每个类只能有一个类对象。

      希望这是有道理的

      【讨论】:

      • 很好的附加点。关于措辞的一个评论,我不知道编辑自己的主题“jvm将使用该信息一个代表堆内存中存在的类的类对象区域。”看起来不正确,后面加上 --> 看起来更合乎逻辑。我在这里吗?请保持一致,谢谢!
      • @Brendon Cheung 当你说'一个代表那个类的Class对象'时,它是一个类,而不是那个类的实例,所以我认为我们应该修改表达式.因为只有“实例”进入堆内存,而不是它们的类。
      【解决方案5】:

      Object类默认是java中所有类的父类。也就是说,它是java的最顶层类。

      如果您想引用任何您不知道其类型的对象,Object 类将非常有用。请注意,父类引用变量可以引用子类对象,称为向上转换。

      举个例子,getObject() 方法返回一个对象,但它可以是任何类型,如 Employee、Student 等,我们可以使用 Object 类引用来引用该对象。例如:

      Object obj=getObject();//我们不知道这个方法会返回什么对象

      【讨论】:

        【解决方案6】:

        Class 对象是 Class (java.lang.Class) 的一个实例。下面从类的 javadoc 中引用应该回答你的问题

        类没有公共构造函数。相反,类对象是由 Java 虚拟机在加载类时自动构造的,并通过调用类加载器中的 defineClass 方法来构造。

        【讨论】:

          【解决方案7】:

          getClass() 是一种返回对象的方法,该对象是java.lang.Class 的实例...不涉及强制转换。投射看起来像这样:

          Class<?> type = (Class<?>) object;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-12-12
            • 1970-01-01
            • 2016-02-22
            • 1970-01-01
            • 2017-03-19
            • 2012-03-02
            • 2015-03-11
            相关资源
            最近更新 更多