先上代码:打印出什么?
package hack;
import click.CodeTalk;
public class TypeIt {
private static class ClickIt extends CodeTalk {
void printMessage() {
System.out.println("Hack");
}
} public static void main(String[ ] args) {
ClickIt clickit = new ClickIt();
clickit.doIt();
}
}package click;
public class CodeTalk {
public void doIt() {
printMessage();
} void printMessage() {
System.out.println("Click");
}
}
打印结果是:Click 很显然,对于private类型的方法,子类里面不能重写;但是这里是缺省的方法,子类里面也不能。
谁能解释下?
package hack;
import click.CodeTalk;
public class TypeIt {
private static class ClickIt extends CodeTalk {
void printMessage() {
System.out.println("Hack");
}
} public static void main(String[ ] args) {
ClickIt clickit = new ClickIt();
clickit.doIt();
}
}package click;
public class CodeTalk {
public void doIt() {
printMessage();
} void printMessage() {
System.out.println("Click");
}
}
打印结果是:Click 很显然,对于private类型的方法,子类里面不能重写;但是这里是缺省的方法,子类里面也不能。
谁能解释下?
解决方案 »
- 关于Java学习之路给点意见月资料
- java与mysql连接,mysql-connector-java-5.1.12-bin.jar要与mysql版本一致吗?
- 关于iframe传值问题
- 请教一个基于继承的多态遇到的不解
- 求一个JACOB调用DLL完整的示例,有心人贡献一下吧
- 请教SimpleDateFormat 的 applyLocalisedPattern 和applyPattern的分别
- 请教三个java问题?急
- 我用了urlConnection对象联接某个http的地址,但是有时候页面会连接很慢,有没有什么办法设定timeout之类的东西,谢谢
- idl的问题???
- dom4j解析xml 修改节点值时报错,求破!
- JPanel的刷新问题 求高手
- java程序问题
public class TypeIt {
private static class ClickIt extends CodeTalk {
void printMessage() {
System.out.println("Hack");
}
} public static void main(String[] args) {
ClickIt clickit = new ClickIt();
clickit.doIt();
}
} class CodeTalk {
public void doIt() {
printMessage();
} void printMessage() {
System.out.println("Click");
}
}
结果是:Hack JDK1.5还好我想不通就运行看下结果。求解!!!!
--
关于访问权限是:public > protected > 默认 > private
·默认:就是什么都不写,它的真正名字是,“包访问权限”,即在同一个包内访问权限为public ,在包外就是private的了。
·protected:就是“继承访问权限”,它是要超越“包”的。包内,同上,public 。 “包”外分情况,如果有继承,也就相当于是 public 的。没有继承,就是 private的。
---
你上面的例子是在两个包的文件,虽然有继承,还是不能重写那个 默认 权限的方法的。
你在ClickIt中定义的printMessage只属于这个类自己,而不是父类中的printMessage。
ClickIt clickit = new ClickIt();
clickit.doIt();
这句是调用了父类中的doIt(),因为父类中的doIt()的访问权限是public,所以子类继承到了,doIt()方法找的是它本类中的printMessage(),所以输出的结果是Click.
首先,先清楚一个概念,方法绑定:
1. 静态绑定,就是在编译时就能确定给定的方法签名对应的方法体。在Java中,私有方法,构造器,父类的方法就是静态绑定,还包括那些编译时就可以确定方法体的方法。
2. 动态绑定,就是在运行时才确定一个方法签名对应的方法体。用于实现多态,Java中大部分方法都是动态绑定的。在JVM上,静态绑定使用invokespecial指令,动态绑定使用invokvirtual。invokevirtual会根据方法签名从当前对象向他的父类进行搜索,直到找到一个方法为止。先看一下CodeTalk和TypeIt在不同包的情况,CodeTalk.class反编译后的结果:# 只截取了doIt方法
public void doIt();
Code:
0: aload_0
1: invokespecial #2; //Method printMessage:()V
4: return LineNumberTable:
line 4: 0
line 5: 4
可以看到在doIt方法的字节码中,调用printMessage方法使用的指令是invokespecial:
1: invokespecial #2; //Method printMessage:()V
也就是说,doIt方法是静态绑定,并且绑定了CodeTalk.printMessage方法。所以这个方法会被调用,打印Click在看ColdTalk和TypeIt在同一包的情况,CodeTalk.class反编译后的结果:# 只截取了doIt方法
public void doIt();
Code:
0: aload_0
1: invokevirtual #2; //Method printMessage:()V
4: return LineNumberTable:
line 16: 0
line 17: 4可以看到printMessage方法调用使用的是invokevirtual,也就是方法是动态绑定的:
1: invokevirtual #2; //Method printMessage:()V
在调用clickIt.doIt()方法时,JVM会从ClickIt类开始向CodeTalk类搜索printMessage:()V这个方法,而ClickIt中定义了这个方法,所以直接返回。最后调用的是ClickIt.printMessage方法,打印Hack。之所以为什么CodeTalk和TypeIt两个类在不在相同包中,会导致printMessage方法调用指令不一样,这是由javac编译器保证的。
总结就是package-private方法不能直接被另外一个包中的方法覆盖
An instance method m1 declared in a class C overrides another instance method, m2, declared in class A iff all of the following are true: C is a subclass of A. The signature of m1 is a subsignature (§8.4.2) of the signature of m2. Either
m2 is public, protected or declared with default access in the same package as C, or
m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2, such that m3 overrides m2. (间接覆盖)Moreover, if m1 is not abstract, then m1 is said to implement any and all declarations of abstract methods that it overrides.