实现接口,方法调用和类型转换的方法

时间:2013-09-27 16:03:10

标签: java compiler-construction

考虑以下代码

interface MyInterface{
    void method(String s);// if we write static modifier we have compile error
}
class MyClass implements MyInterface{
    public static void main(String[] args){
        myMethod(new Object());//Compile error
    }
    static void method(String s){...}// compile error
    static void myMethod(Number n){...}

}
  1. 为什么我们不能在接口中定义静态方法?
  2. 为什么我们无法使用static修饰符实现method()
  3. 当我们通过引用Object调用myMethod时,我们有编译错误。据我所知,编译器不会自动投射,不是吗?
  4. 请考虑以下代码

    Object someObj; ... Number n= (Number) someObj;

  5. 在这种情况下,当我们转换为Number时,编译器正在做什么?

3 个答案:

答案 0 :(得分:4)

  

为什么我们不能在接口中定义静态方法?

默认情况下,接口的所有方法都是public abstract。使用static修饰符并不合理。因为静态方法的调用不是多态的。从某种意义上说,你无法覆盖它们。您只能在类名上调用静态方法。好吧,你也可以在一些引用上调用它们,但最终将根据声明的引用类型来解决。现在,由于该方法默认是抽象的,因此调用它是没有意义的。它没有任何机构可以完成任何任务。

  

为什么我们不能用static修饰符实现method()?

当您尝试将static修饰符添加到重写方法时,不会将其视为重写。因此,您的类本质上有两种不同的方法,具有相同的名称,相同的参数和相同的返回类型。这当然不允许在课堂上。

请注意,您必须向类中的重写方法显式添加public修饰符,否则您的代码将无法编译。原因是,您无法降低子类中重写方法的可见性。

  

当我们通过引用Object调用myMethod时,我们有编译错误。据我所知,编译器不会自动转换,不是吗?

Jave没有自动缩小转换。您需要显式添加强制转换。但即使它允许,您希望代码如何表现,因为您试图引用具有子类引用的超类对象?您当然可以通过在调用方法时添加强制转换来编译代码:

myMethod((Number)new Object());  // This will compile, but fail at runtime

上面的调用将在运行时产生ClassCastException

但是,如果你有Object引用引用Number的任何子类的对象,你可以添加一个显式类型转换,这将是类型安全的:

Object obj = new Integer(5);
Number num = (Number)obj;  // This is fine. Because `obj` is referring to an `Integer`.

最后,main方法的签名不正确。您缺少public修饰符。

答案 1 :(得分:2)

  

为什么我们不能在接口中定义静态方法?

接口设计用于处理多态,基本上。多态性在接口上调用静态方法时,您如何知道要调用哪个实现?

// Should that invoke MyClass.method or MyOtherImplementation.method?
MyInterface.method("foo");

下一步:

  

为什么我们不能用static修饰符实现method()?

这个想法是在一些实现接口的对象上调用该方法 - 这使它成为一个实例方法。

  

当我们通过引用Object调用myMethod时,我们有编译错误。据我所知,编译器不会自动转换,不是吗?

不,编译器不会自动转换。没有从ObjectNumber的隐式转换,因此您无法使用类型为Number的参数调用类型为Object的参数的方法。

  

在这种情况下,当我们转换为Number时,编译器正在做什么?

验证someObj的值是null还是对Number实例或子类的引用。

答案 2 :(得分:0)

直到JDK7:

  1. 因为静态方法绑定到类。你正常地像这样调用它们:

    MyClass.method("");
    

    你无法覆盖它们。

  2. 请参阅1,所有界面方法均为public abstract,您无法更改!

  3. 编译器没有自动投射

  4. 他试图施放并失败

相关问题