考虑以下代码
1 2 3 4 5 6 7 8 9 10 11
| 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 ){... }
} |
为什么我们不能在接口中定义静态方法?
为什么不能用静态修饰符实现method()?
当我们引用对象调用MyMethod时,出现了编译错误。据我所知,编译器不会自动强制转换,不是吗?
考虑以下代码
Object someObj;
...
Number n= (Number) someObj;
在本例中,当我们强制转换到Number时,编译器在做什么?
- 明白我们为什么要将接口方法声明为公共的吗?
- @选择不同的主题。与这个问题无关
- 你问了几个不同的问题,每个问题都应该单独问。第一个可能是接口中为什么不能声明静态方法的副本?.
Why we cant define static method in interface?
默认情况下,接口的所有方法都是public abstract。使用static修饰语没有意义。因为静态方法的调用不是多态的。从某种意义上说,你不能重写它们。只能对类名调用静态方法。好吧,您也可以在某些引用上调用它们,但最终将根据声明的引用类型来解决这一问题。现在,由于该方法在默认情况下是抽象的,所以调用它是没有意义的。它没有任何身体来完成任何任务。
Why we cant implements method() with static modifier?
当您试图向重写方法添加static修饰符时,它不会被视为重写。所以,类本质上有两个不同的方法,具有相同的名称、相同的参数和相同的返回类型。当然,这在类中是不允许的。
注意,您必须显式地向类中的重写方法添加public修饰符,否则代码将无法编译。原因是,您不能降低子类中被重写方法的可见性。
When we are calling myMethod with reference to Object we have compile error. As i understood, compiler doesnt cast automatically, isnt it?
Jave不进行自动缩小转换。您需要显式添加强制转换。但即使它允许,您希望代码的行为如何,因为您正试图用子类引用引用一个超类对象?当然,可以通过在调用方法时添加强制转换来编译代码:
1
| myMethod ((Number)new Object()); // This will compile, but fail at runtime |
上述调用将在运行时产生一个ClassCastException。
但是,如果您的Object引用引用了Number任何子类的对象,则可以添加一个显式强制转换,这将是类型安全的:
最后,您的main方法的签名不正确。您缺少public修饰符。
- 注意,Java 8的接口可以有静态方法。
- 阿沙吉。是的,Java 8有默认方法,但是我不考虑这里,假设OP还没有使用Java 8。
- @Rohit Jain在你的例子中,当我们向Number:Object obj = new Integer(5); Number num = (Number)obj;投射时会发生什么?编译器将(Number)obj解析为对Number的某种引用?
- 圣安东里奥。编译器将添加强制转换,正如您已经明确说过的。编译器处理引用类型。现在,在运行时,根据引用引用的实际对象,转换可能会失败或成功。因为在您的例子中,实际对象是new Integer(5);,您可以很容易地将其分配给Number引用,所以强制转换成功。
- 圣安东里奥。如果obj = null;是有效的参考值,那么强制转换也会成功,因为null是有效的参考值。
- @Rohit Jain如果我们在编译时显式地进行强制转换会发生什么?编译时的(Number)obj是什么?我认为它是对Number的一些引用,比如编译时的Number someNumber;。是否所有的强制转换都在运行时调用?
- 圣安东里奥。强制转换总是在运行时完成。使用(Number)obj,您只需将obj的引用类型强制转换为Number。我建议您浏览jls部分-docs.oracle.com/javase/specs/jls/se7/html/jls-5.html jls-5.1
- @RohitJain我想了解编译器如何从引用类型obj转换为Number。编译器只是把(Number)obj看作是对Number的引用还是什么?
- @Rohit Jain从类型线程到类型对象的转换不需要运行时操作;线程是对象的子类,因此类型线程表达式生成的任何引用都是类型对象的有效引用值。例如,Integer ints= new Integer(2);Number n=ints;为什么编译器知道Integer是Number的子类型?他是否检查了Number的源代码,直到找到Integer或Number的所有子类型?
- @St.antario编译器查找Number和Integer的声明,并知道Integer是Number的子类型。什么部分让你困惑?
- @Rohit Jain好的,谢谢!最后一个问题:在这种情况下,Number num = (SomeType)obj编译器会查找声明号和sometype,并检查sometype子类型是否为number?请回答是或否。
- 圣安东里奥。在某种程度上,是的。
- 圣安东里奥。如果你现在的怀疑是清楚的,那么你可以把答案标为接受。
Why we cant define static method in interface?
基本上,接口设计用于多态性。多态性在接口上调用静态方法时,您如何知道要调用哪个实现?
1 2
| // Should that invoke MyClass.method or MyOtherImplementation.method?
MyInterface.method("foo"); |
下一步:
Why we cant implements method() with static modifier?
其思想是在实现接口的某个对象上调用该方法,这使它成为实例方法。
When we are calling myMethod with reference to Object we have compile error. As i understood, compiler doesnt cast automatically, isnt it?
不,编译器不会自动强制转换。没有从Object到Number的隐式转换,因此不能使用Number类型的参数和Object类型的参数调用方法。
What compiler is doing when we cast to Number in this case?
它验证了someObj的值是空的,或者引用了Number或子类的实例。
直到JDK7:
因为静态方法绑定到类。您通常这样调用它们:
您不能覆盖它们。
见1,所有接口方法都是public abstract,不能更改!
不编译器不会自动强制转换
他试着投,但失败了。