读书人

散分贴,对于interface和Object关系的思

发布时间: 2011-12-10 00:07:34 作者: rapoo

散分贴,关于interface和Object关系的思考!
其实这个问题讨论起来没什么意义,不过大半夜睡不着,写点东西散个分.

下面是一个最简单的interface:
interface I {}
这个 I 和 Object 到底有什么关系呢?

问题一:
public class T {
public static void main(String[] args) {
I i;
}
}
上面一个简单的类,用eclipse的时候在I i;下面面输入 "i. "会出现Object的方法列表.
显然即时编译器编译通过了才会出现这种结果.为什么?

问题二:
interface Test {
public int toString();
}
接口改成上面这个样子.编译后有如下错误:
Test.java:2: Test 中的 toString() 无法覆盖 java.lang.Object 中的 toString();正在尝试使用不兼容的返回类型
找到: int
需要: java.lang.String
public int toString();
^
1 错误

问题三:
再改改这个接口:
interface Test {
public void wait();
}
编译后有如下错误:
Test.java:2: Test 中的 wait() 无法覆盖 java.lang.Object 中的 wait();被覆盖的方法为 final
public void wait();
^
1 错误


要回答这三个问题,就先要回答interface和Object的关系.
从java程序设计语言的角度上将interface不是类,而Object是所有类的最终超类.
所以从这里看interface和Object没有必然联系.

但是看看java language specification中怎么说:
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.

It follows that is a compile-time error if the interface declares a method with a signature that is override-equivalent (§8.4.2) to a public method of Object, but has a different return type or incompatible throws clause.

简单的说就是:
如果接口没有直接超接口,那么该接口会隐式声明一些public abstract的方法,这些方法和Object中的public方法具有对应的方法签名,返回类型,异常列表.
如果在接口中显示声明了Object中的final的方法,报错.
如果在接口中声明的方法和Object中的方法具有相同的方法签名,但是返回类型不同或者异常列表不相容,报错.

按照上面的说法,给与了前三个问题合理的解释.
interface不是类,与Object的关系更谈不上继承.但它和Object的关系密切,它将Object的public方法都声明为了abstract.

但是问题并没有就此结束...
还是这个interface I {}
编译后javap -verbose看看:
常量池Constant pool:
const #1 = class #5; // I


const #2 = class #6; // java/lang/Object
const #3 = Asciz SourceFile;
const #4 = Asciz I.java;
const #5 = Asciz I;
const #6 = Asciz java/lang/Object;
可以明确的说:
const #1 = class为this_class项所指.
const #2 = class为super_class项所指.

再看看这个:
interface M extends i {}
常量池 Constant pool:
const #1 = class #6; // M
const #2 = class #7; // java/lang/Object
const #3 = class #8; // I
const #4 = Asciz SourceFile;
const #5 = Asciz I.java;
const #6 = Asciz M;
const #7 = Asciz java/lang/Object;
const #8 = Asciz I;
其中
const #1 = class仍为this_class项所指.
const #2 = class仍为super_class项所指.仍然是java/lang/Object
而const #3 = class是interfaces数组项所指.
I被指为M的interface,相当于implements,而并不像声明中说的extends.

insideJVM中指出任何interface的super_class项均为java/lang/Object.
只有java/lang/Object的super_class项为0.

再看下下面的代码
class Test {
void f() {
I i = null;
i.toString();
}
}
f()的指令操作码:
void f();
Code:
Stack=1, Locals=2, Args_size=1
0: aconst_null
1: astore_1
2: aload_1
3: invokevirtual #2; //Method java/lang/Object.toString:()Ljava/lang/String;
6: pop
7: return

关键的这句:
3: invokevirtual #2; //Method java/lang/Object.toString:()Ljava/lang/String;
编译器在处理i.toString()的时候是查看的i的声明类型,也就是I.
要知道这个时候编译器只知道i的类型是I,对i的实际类型是不知道的.如果I没有toString方法,那么编译器就会去I的super_class项指定的类中去找.
而最后动态绑定上的是Object的toString.
当然可以按前面的解释,interface隐式声明了toString方法,然后映射到Object的toString的方法.但是与其用这种牵强的解释,不如解释成interface的超类就是Object(至少在编译器和虚拟机是这么看的)来的合适.

最后我想说的是,规范和实现是两个层面上的东西,不能混为一谈,但又经常分不清...

[解决办法]
JF
[解决办法]


Q:

下面是一个最简单的interface:
interface I {}
这个 I 和 Object 到底有什么关系呢?


A:

这个I和Object没有任何关系,Object是类和抽象类的基类,而不是接口的基类。
[解决办法]
很有研究精神,值的学习。
[解决办法]
up
[解决办法]
up!
[解决办法]
我刚学JAVA一个星期,还没看懂你所说的东东,不过以后我还会来看你的帖的。
UP!!
[解决办法]
jf
[解决办法]
jf
[解决办法]
UP
[解决办法]
恩.强.以前只注意到object 是所有类的超类,没有注意这些.

jf
[解决办法]
尽信书 不如无书
书不是规范 只不过是前人理解的总结

I.class instanceof Object
这个是ture的
那说明interface 应该是继承Object的

另外从interface的文件也是.class来看 interface应该是一个特殊的类
特殊的类 叫接口


另外 就算用一个interface声明 来持有一个对象
也是可以肯定这个对象是继承Object的 所以其中的方法肯定是存在的
所以完全可以对interface声明调用Object方法
[解决办法]
不错,值得学习,支持楼上的楼上说的。
[解决办法]
纯接分
[解决办法]

[解决办法]
我也是来接份的啊!
[解决办法]
其实只需要简单的理解成,接口和类没有关系,但接口不被类实现就没有意义。而如果一个接口一旦被某个类实现,那这个类就一定会具有Object的方法。因此一个接口中申明的方法不能和Object的方法冲突。

或者,可以理解为Interface也是从Object继承。所以一个接口类型的变量会具有Object的方法。但是,由于这个变量的值实际是null,所以即使调用这个Object中的某些方法,也只会得到NulLPointerException。语法上虽然没有问题,但执行起来却是个不折不扣的毫无意义的东西。
[解决办法]
类和接口可以看成两个平级的,在一个类里面不可以new接口,只能new接口的实现类

[解决办法]
看不明白
up!!
[解决办法]
貌似有点像“鸡和蛋的关系”`````
[解决办法]
学习!jf
[解决办法]
学习
[解决办法]
学习,顺便接分~~~
[解决办法]
学习

[解决办法]
古人都说了,不求甚解
[解决办法]
呵呵.楼主是研究院的?
[解决办法]
.class instanceof Object
这个是ture的
那说明interface 应该是继承Object的

另外从interface的文件也是.class来看 interface应该是一个特殊的类
特殊的类 叫接口


另外 就算用一个interface声明 来持有一个对象
也是可以肯定这个对象是继承Object的 所以其中的方法肯定是存在的
所以完全可以对interface声明调用Object方法


[解决办法]
JavaEE高手进入
QQ群 5294054

读书人网 >J2SE开发

热点推荐