首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

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

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

散分贴,关于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

热点排行