Interface的Object之间的关系问题
一直没有读过什么经典的Java书籍,有时候被学员拿着《think in java》中一些看不懂的地方来问我,我才顺便跟着看上一页两页的。我现有的java知识都是零零散散收集的和在大量的教学实践中自我总结的,所以,我掌 握的java知识体系不够系统。我现在有一个非常基础的问题,不知道有没有朋友能够给出权威的解释,最好能给出解释的原文出处,鄙人将不胜感激!
一 个接口没有继承Object类,但我们在任何接口上调用Object类的方法,编译器都不报错,这种现象该如何解释呢?例如,下面的代码中 Runnable是一个接口,但我们针对这个接口调用了Object类的一些方法,可以成功通过编译,是不是编译器对这种情况进行了特殊对待?
class InterfaceAndObject
{
public void interfaceTest(Runnable r)
{
System.out.println(r.toString() + r.hashCode());
}
}
这是张孝详blog上的内容
http://blog.csdn.net/zhangxiaoxiang/archive/2006/09/03/1173253.aspx?Pending=true
我样应该是这样的。
一般,如果一个类未继承任何类,那么编译器将使用两种方法处理。
1:为这个类指定一个默认的类来继承,c#就是这样。
2:由解析器来处理,即如果发现某个类未从任何类继承,就将这个类强行解释为从一个默认类继承,但
并不将继承的代码写的二进制执行文件中。
下面就来证明我的观点。其实要证明这一点非常简单。由于c#和java最终都生成中间语言,并且不管源码
是什么样,生成的中间语言都会保持原始状态,即如果是在编译时将这个默认父类加上,虽然在源码中未
继承这个父类,但在中间语言中必然会有所体现。
这是一个java类
class MyClass implements Runnable
{
public void run()
{
}
}
使用DJ java Decompiler进行反编译,反编译成字节码
class MyClass
implements Runnable
{
MyClass()
{
// 0 0:aload_0
// 1 1:invokespecial #10 <Method void Object()>
// 2 4:return
}
public void run()
{
// 0 0:return
}
}
可以看出,并未有extends Object出现。
而看下面一段c#代码(由于C#没有Runnable接口,因此,定义一个)
interface Runnable
{
void run();
}
class MyClass : Runnable
{
public void run()
{
}
}
使用c#自带的ildasm.exe反编译成中间语言
.class private auto ansi beforefieldinit WindowsApplication1.MyClass
extends [mscorlib]System.Object
implements WindowsApplication1.Runnable
{
} // end of class WindowsApplication1.MyClass
可以看到多出个extends [mscorlib]System.Object来,因此,c#是编译在编译时自动加上的
System.Object,而java是由解析器来自动解析的(java的编译器源码是什么就编译成什么样子,而不像
c#的编译器,加一些额外的东西。
最后看一下Runnable.class的反编译结果
public interface Runnable
{
public abstract void run();
}
可就是一个单独定义的接口,它可没从Object继承。
一直没有读过什么经典的Java书籍,有时候被学员拿着《think in java》中一些看不懂的地方来问我,我才顺便跟着看上一页两页的。我现有的java知识都是零零散散收集的和在大量的教学实践中自我总结的,所以,我掌 握的java知识体系不够系统。我现在有一个非常基础的问题,不知道有没有朋友能够给出权威的解释,最好能给出解释的原文出处,鄙人将不胜感激!
一 个接口没有继承Object类,但我们在任何接口上调用Object类的方法,编译器都不报错,这种现象该如何解释呢?例如,下面的代码中 Runnable是一个接口,但我们针对这个接口调用了Object类的一些方法,可以成功通过编译,是不是编译器对这种情况进行了特殊对待?
class InterfaceAndObject
{
public void interfaceTest(Runnable r)
{
System.out.println(r.toString() + r.hashCode());
}
}
这是张孝详blog上的内容
http://blog.csdn.net/zhangxiaoxiang/archive/2006/09/03/1173253.aspx?Pending=true
我样应该是这样的。
一般,如果一个类未继承任何类,那么编译器将使用两种方法处理。
1:为这个类指定一个默认的类来继承,c#就是这样。
2:由解析器来处理,即如果发现某个类未从任何类继承,就将这个类强行解释为从一个默认类继承,但
并不将继承的代码写的二进制执行文件中。
下面就来证明我的观点。其实要证明这一点非常简单。由于c#和java最终都生成中间语言,并且不管源码
是什么样,生成的中间语言都会保持原始状态,即如果是在编译时将这个默认父类加上,虽然在源码中未
继承这个父类,但在中间语言中必然会有所体现。
这是一个java类
class MyClass implements Runnable
{
public void run()
{
}
}
使用DJ java Decompiler进行反编译,反编译成字节码
class MyClass
implements Runnable
{
MyClass()
{
// 0 0:aload_0
// 1 1:invokespecial #10 <Method void Object()>
// 2 4:return
}
public void run()
{
// 0 0:return
}
}
可以看出,并未有extends Object出现。
而看下面一段c#代码(由于C#没有Runnable接口,因此,定义一个)
interface Runnable
{
void run();
}
class MyClass : Runnable
{
public void run()
{
}
}
使用c#自带的ildasm.exe反编译成中间语言
.class private auto ansi beforefieldinit WindowsApplication1.MyClass
extends [mscorlib]System.Object
implements WindowsApplication1.Runnable
{
} // end of class WindowsApplication1.MyClass
可以看到多出个extends [mscorlib]System.Object来,因此,c#是编译在编译时自动加上的
System.Object,而java是由解析器来自动解析的(java的编译器源码是什么就编译成什么样子,而不像
c#的编译器,加一些额外的东西。
最后看一下Runnable.class的反编译结果
public interface Runnable
{
public abstract void run();
}
可就是一个单独定义的接口,它可没从Object继承。