【问题标题】:Casting Object Types铸造对象类型
【发布时间】:2013-12-29 14:16:52
【问题描述】:

我对转换对象类型有点困惑。举个例子:

public class Test() {

 public void method1() { System.out.println("Method 1");
 public void method2() { System.out.println("Method 2");
 }

public class Test1() extends Test{

  @Override public void method1() { System.out.println("Method 11");
  @Override public void method2() { System.out.println("Method 22");
   public void method 3() { System.out.println("Method 3");

   public static void main(String[] args) {
       Test a = new Test1(); 
       a.method1(); //method invokes the overridden method1() of Test1, not Test the superclass
       a.method2(); //method invokes the overridden method2() of Test1, not Test the superclass
       a.method3(); //error, must cast == ((Test1)a).method3();
    }
}

我很困惑的是当我调用method1和method2时,编译器或JVM能够调用派生类或子类的方法,那么为什么仍然需要向下转换/转换才能调用method3( )?

我尝试重载超类的method1和method2而不是重写它;编译器/JVM 将要求您在允许您调用重载方法之前向下转换对象引用变量。那么,这意味着在没有向下转换的情况下,您只能调用超类的方法以及子类中定义的覆盖方法?

【问题讨论】:

    标签: java casting


    【解决方案1】:

    您的引用a 的类型为Test,但method3Test 中不存在。

    Test a = new Test1();
    // ^-reference   ^-object 
    //   type          type
    

    规则:

    • 引用类型告诉我们哪些方法是可见的。
    • 对象类型告诉我们考虑了哪些可见方法的实现。


    这是我能想到的最基本的例子之一:
    public class Animal
    {
         public void speak()
         {
              System.out.println("BLARGHGH");
         }
    }
    
    public class Dog extends Animal
    {
         @Override
         public void speak()
         {
              System.out.println("Woof");
         }
    }
    
    public class Cat extends Animal
    {
         @Override 
         public void speak()
         {
              System.out.println("Meow");
         }
    
         public void throwUpFurball()
         {
              System.out.println("So fluffy!");
         }
    }
    
    public class Test()
    {
         public static void main(final String args[])
         {
              Animal animal1 = new Animal(); 
              animal1.speak(); // BLARGHGH
              animal1.throwUpFurball(); // Compilation error - method not found. It will ask for casting
    
              Animal animal2 = new Cat();
              animal2.speak(); // Meow
              ((Cat)animal2).throwUpFurball(); // Must be cast, because throwUpFurball does not exist in Animal
    
              Animal animal3 = new Dog();
              animal3.speak(); // Woof
              ((Cat)animal3).throwUpFurball(); // Compiles, but throws ClassCastException at runtime, because the object type of animal3 is Dog
    
              Cat animal4 = new Cat();
              animal4.speak(); // Meow
              animal4.throwUpFurball(); // No casting necessary, because animal4 is of type Cat
    
              Object animal5 = new Animal();
              animal5.speak(); // Again, compilation problem. The type Object does not contain the speak() API, so it will require casting.
         }
    }
    

    【讨论】:

    • Test中不存在被覆盖的method1()和method2(),为什么可以调用呢?
    • @Marz 因为您将它们添加到Test,所以它们是公开可用的,如果您覆盖它们,将调用覆盖的方法。
    • @Marz 这是错误命名的问题。当您提出和回答代码问题时,它会变得混乱。当然method1method2 存在于Test 中。你自己声明了它们。另外,这就是我在答案中添加这些规则的原因。在您的情况下,执行覆盖的实现。
    • @GGrec:我很抱歉命名不好。我只是虚构了这一切,没有考虑实际情况,我的错。无论如何,您是说编译器/JVM 基本上可以调用/到达子类的所有方法;只是它们只允许您调用在声明为引用类型的类中也定义/声明的方法?某种规则之类的?
    • @Marz will only allow you to call the methods that are also defined/declared in the class declared as the reference type Bingo。我添加了一个例子来澄清。 :-)
    【解决方案2】:

    你可以试试Test1 a = new Test1(); - 引用应该清楚!

    ps:用 } 关闭你的方法;只是因为... AND 方法 3() 应该是 method3()

    :)

    希望我没听错!

    public class Test1() extends Test{
    
      @Override public void method1() { System.out.println("Method 11");}
      @Override public void method2() { System.out.println("Method 22");}
       public void method3() { System.out.println("Method 3");}
    
       public static void main(String[] args) {
           Test1 a = new Test1(); 
           a.method1(); //method invokes the overridden method1() of Test1, not Test the superclass
           a.method2(); //method invokes the overridden method2() of Test1, not Test the superclass
           a.method3(); //error, must cast == ((Test1)a).method3();
        }
    }
    

    【讨论】:

    • 对不起,我忘了放一个结束符},并且不小心在方法和3之间放置了一个空格。无论如何,我知道如何让它运行,我只是困惑它是如何工作的。 :D
    • 哈哈,我明白了 :) 这是典型的编程:它运行,但你不知道为什么----或者有一个错误,你找不到它哈哈哈
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    相关资源
    最近更新 更多