【问题标题】:Why must casting to a derived class be explicit rather than implicit为什么强制转换为派生类必须是显式的而不是隐式的
【发布时间】:2014-12-19 15:23:48
【问题描述】:

Object o = new Student(); // Implicit casting

我非常了解这段代码,我的理解是引用变量“o”指的是“Object”类型的数据,我们可以看到 Student 是从“Object”扩展而来的,这意味着它指的是学生。 如果我写了以下代码:

Object x = o;

这会将 o 中的值分配给 x ,这意味着如果我们遵循 x 的方向,我们将转到上面的那个学生对象!

我的问题是,为什么我不能写下面的代码? :

Student x = o;

“o”指的是“Object”类型的对象,该对象将其地址(在内存中)分配给“o”,为什么我们不能将保存在o中的值分配给x!

【问题讨论】:

  • 这可能会产生非常困难的错误和神秘的代码。编译器也无法轻松处理此功能。这显然是可能的,所以我认为这是一个伟大的设计决策。
  • 因为 Java 的设计者没有选择复制 Visual Basic。这是他们的口味问题。

标签: java object casting implicit


【解决方案1】:

这里没有演员。

正如你所说,ObjectStudent 的基类。
这意味着Student 的每个实例也是Object,我们总是可以将其视为一个。

Object o = new Student(); // A Student is an Object

然而,相反的关系并不成立 - 并非所有 Object 的实例都是 Students。

Student 分配给o 后,编译器无法获得实际上Student 的信息。
该信息在运行时可用 - 你可以说 o instanceof Student 它会 是真的 - 但编译器不知道这一点。

【讨论】:

    【解决方案2】:
    Object o = new Student();  //upcasting - Implicit cast
    Student x = (Student) o;   //downcasting -Explicit cast
    

    向上转换:我们正在缩小引用转换(向上移动继承层次结构)。由于是 Student IS-A 对象,因此不需要显式强制转换

    向下转换:我们正在扩大引用转换(向下移动继承层次结构)。由于 Object 可以是任何东西,我们必须使用显式转换将其转换为 Student。

    【讨论】:

      【解决方案3】:
      Object o;
      
      if (Math.random < 0.5) {
        o = new Student();
      } else {
        o = new Dog();
      }
      

      你显然不能拥有Student x = o;

      除非狗也是学生,但那是另一回事。

      【讨论】:

        【解决方案4】:

        Java 只允许隐式向上转换,不允许隐式向下转换。

        在Java中向上转型也称为加宽转换,向下转型称为窄化转换。

        对象可以隐式或显式转换为超类型。在本例中,ObjectStudent 的超类型。

        Object o = new Student();
        Object x = o; // implicit works
        Object x = (Object) o; // explicit works
        

        对象不能隐式转换为子类型,必须显式转换。在此示例中,StudentObject 的子类型。

        Object o = new Student();
        // Student x = o; // implicit doesn't work
        Student x = (Student) o; // explicit works
        

        Explicit and Implicit Type Casting - Herong Yang

        5.1.5. Widening Reference Conversion - Java docs

        5.1.6. Narrowing Reference Conversion - Java docs

        【讨论】:

          【解决方案5】:

          您需要将其显式转换为 Student

          Student x = (Student) o;
          

          这是因为编译器不知道这是否正确,因此您需要将其转换为表示“我相信这会起作用。请相信我” .

          【讨论】:

            【解决方案6】:

            您可以将 Student 的实例分配给声明为 Object 类型的变量,因为每个 Student 都是 Object 的一种(或特化)。由于不是每个对象都是学生,因此编译器拒绝将它知道的对象分配给对象的任何特化,例如学生。因此,您可以毫无困难地隐式分配给更通用类型的实例变量,但在相反的方向上,编译器需要一些保证您的意思是这样做,所以您明确地向下转换。

            Student x = (Student)o;
            

            这只是静态类型语言的本质。

            【讨论】:

              【解决方案7】:

              你基本上必须看看它是否通过了IS-A 测试,你可以说Student IS-A Object(因为Java 中的每个类都是Object 类的子类),这就是第一个隐式强制转换起作用的原因。

              但是你不能说Object IS-A Student,因为它可能不是。除非您知道它将是 Student,否则您可以通过以下方式进行 downcast

              Student x = (Student) o;
              

              以防万一您对 downcast 有误,您可能希望将其包装在 if 语句中,如下所示:

              if(o instanceof Student) {
                  Student x = (Student) o;
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-07-14
                • 1970-01-01
                • 2019-02-06
                • 2021-06-01
                • 1970-01-01
                • 2015-02-24
                • 1970-01-01
                • 2011-07-15
                相关资源
                最近更新 更多