其实这个问题讨论起来没什么意义,不过大半夜睡不着,写点东西散个分.下面是一个最简单的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(至少在编译器和虚拟机是这么看的)来的合适.最后我想说的是,规范和实现是两个层面上的东西,不能混为一谈,但又经常分不清...
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(至少在编译器和虚拟机是这么看的)来的合适.最后我想说的是,规范和实现是两个层面上的东西,不能混为一谈,但又经常分不清...
interface I {}
这个 I 和 Object 到底有什么关系呢?A:这个I和Object没有任何关系,Object是类和抽象类的基类,而不是接口的基类。
interface Test {
public int toString();
}
接口改成上面这个样子.编译后有如下错误:
Test.java:2: Test 中的 toString() 无法覆盖 java.lang.Object 中的 toString();正在尝试使用不兼容的返回类型
找到: int
需要: java.lang.String
public int toString();
^
1 错误答案:因为任何一个接口的存在的目的是让一个具体的类去实现它,而实现这个接口的这个类,即默认的继承了Object的toString,由于接口又定义了toString方法,这两个方法它们的返回类型仅仅不同,因此,会有错的。
再改改这个接口:
interface Test {
public void wait();
}
编译后有如下错误:
Test.java:2: Test 中的 wait() 无法覆盖 java.lang.Object 中的 wait();被覆盖的方法为 final
public void wait();
^
1 错误问题和上面的第二个问题类似,因为Object里面的wait是final的,因此,改方法不能被继承重写,而接口Test定义了一个wait方法,改方法和Object方法的唯一不同是,Object的wait方法
的原型是final的,在Java中,不能有一个类,继承一个类A和一个接口B,类A有一个和接口B相同的方法,而类A的方法确实final的,不知道说清楚了没有?
UP!!
书不是规范 只不过是前人理解的总结I.class instanceof Object
这个是ture的
那说明interface 应该是继承Object的另外从interface的文件也是.class来看 interface应该是一个特殊的类
特殊的类 叫接口
另外 就算用一个interface声明 来持有一个对象
也是可以肯定这个对象是继承Object的 所以其中的方法肯定是存在的
所以完全可以对interface声明调用Object方法
但是有书在那摆着,也不好说什么.而且毕竟将interface解释成继承Object还是有一些地方说不通的.另外编译器和虚拟机的实现也是各有差异的.
顺便问一句,说到规范,那
<Java Language Specification>算不算规范?
<Java Virtual Machine Specification>算不算规范?
这个是ture的
那说明interface 应该是继承Object的另外从interface的文件也是.class来看 interface应该是一个特殊的类
特殊的类 叫接口
另外 就算用一个interface声明 来持有一个对象
也是可以肯定这个对象是继承Object的 所以其中的方法肯定是存在的
所以完全可以对interface声明调用Object方法
这个是ture的
那说明interface 应该是继承Object的我不知道所说的.class表示什么意思?为什么.class可以用于instanceof 操作?任何一个继承自Object的类,都应该有个class静态常量,但是任何一个interface却没有这个常量?从这一点上,敢说interface继承自Object?再一点,Object作为一个具体的类类型,占用实际的内存空间8个字节,而地球人都知道Interface实际上是不占用空间的,从这一点上,敢说interface继承自Object?这个问题讨论下去没什么意义了,
既然是散分贴,请散分接贴吧。
QQ群 5294054
不过从.class instanceof Object的结果为true来看,倒是很有道理的.
...
这句话能判断是不是继承Object?
那String.class instanceof String呢?