public class Base{
public static final String FOO = "foo";
public static void main(String []arg){
Base b = new Base();
Sub s = new Sub();
System.out.println(Base.FOO);
System.out.println(Sub.FOO);
System.out.println(b.FOO);
System.out.println(s.FOO);
System.out.println(((Base)s).FOO);//A处 System.out.println("(Base)s : getClassName = " + ((Base)s).getClass().getName());//此处输出为Sub,为何A处输出却不是Sub.Foo 的值bar,而是foo呢?? }
}class Sub extends Base{
public static final String FOO = "bar";
}
解决方案 »
- static synchronized 和 non-static synchronized的区别
- 菜鸟程序问题求助,打酱油的各位高手帮帮忙进来看看啊
- 关于java.util下的Collection 的问题
- 关于泛型设计的一个问题,诸位大侠来关注一下。
- Java中socket编程中的问题
- 一个动态显示问题,GUI高手请进!(有源码)
- ***共享软件,卖的不好,大家帮我看看什么原因?已经没有动力升及了。***
- 简单问题——applet中用相对路径设置JButton的Icon问题,在线给分
- 对话框里,如何将焦点设到指定的按钮
- 关于java 定时查询数据库的问题
- 请问如何在JAVA里做 模糊查询。
- 如何知道我程序运行了多少毫秒?程序占用多少内存
首先对于A处,s向上转型为父类型,再调用FOO,如果此时父类有变量FOO则就执行父类的,如果父类没有再执行子类的,这个没话说。
再看第二处,这个涉及到RTTI(运行时类型信息):
在java里,类型信息在运行时是如何表示的呢?是通过被称为Class对象的特殊对象来完成的,它包含了类有关的信息,每一个类都有一个Class对象
换言之,每当编写并且编译一个新类时就会产生一个Class对象(保存在同名的.class文件中),而调用一个对象的getClass()方法实际上把保存在对象中
的记录本类信息的特殊对象Class对象拿出来,而这当然就是只本来产生对象的那个类了。 建议楼主再看看关于java运行时类型信息方面的知识.
以上代码运行后,输出java.lang.String
很明显我们可以看出,getClass()方法是由对象调用
并返回这个对象所在最小范围内的类名
所以((Base)s).getClass().getName())是Sub((Base)s).FOO
很明显,static字段由类来调用,而父类中有FOO这个字段,
所以是foo
你这话怎么都是说反的呢
应该是父类的引用指向子类的对象,这是upcasting,但这哪里是多态的体现?
成员变量,静态变量都没有多态这个概念,是谁的引用就调谁的
静态变量的调用就像楼上某位同志说的,跟class相关,跟具体的instance没有关系,而且通常也不建议instance.staticVal这样的调用方式至于那个getClass方法才是多态的
而是将s这个指向子类的引用转换成了指向父类的引用,2楼的这句话我不太认同:首先对于A处,s向上转型为父类型,再调用FOO,如果此时父类有变量FOO则就执行父类的,如果父类没有再执行子类的,这个没话说。
如果父类没有,显然也不会执行子类的,编译就不会通过,这就是向上转型的时候丢失类型的结果,(Base)s的结果是s仍然指向着子类对象,但是调用时会执行
父类的代码。
接着(Base)s调用 getClass();getClass()是Object的方法
public final Class<? extends Object> getClass()返回一个对象的运行时类。该 Class 对象是由所表示类的 static synchronized 方法锁定的对象。
红字所写我的理解就是该class对象是不可以更改的
返回:
表示该对象的运行时类的 java.lang.Class 对象。
Class 类的实例表示正在运行的 Java 应用程序中的类和接口
显然s指向的是一个sub的对象调用getClass()返回sub也就合理
很明显我们可以看出,getClass()方法是由对象调用
并返回这个对象所在最小范围内的类名
所以((Base)s).getClass().getName())是Sub2,((Base)s).FOO
很明显,static字段由类来调用,而父类中有FOO这个字段,是父类的引用指向子类的对象,说具体点就是强制类型转换,所以调用的是父类的方法
所以是foo
public static final String FOO = "foo";
public static void dip(){
System.out.println("1");
}
public void dip2(){
System.out.println("2");
}
public static void main(String []arg){
Base b = new Base();
Base s = new Sub();
b.dip();
s.dip();
b.dip2();
s.dip2();
System.out.println(Base.FOO);
System.out.println(Sub.FOO);
System.out.println(b.FOO);
System.out.println(s.FOO);
System.out.println(((Base)s).FOO);//A处 System.out.println("(Base)s : getClassName = " + ((Base)s).getClass().getName());//此处输出为Sub,为何A处输出却不是Sub.Foo 的值bar,而是foo呢??[/color] }
}
}
class Sub extends Base{
public static final String FOO = "bar";
public static void dip(){
System.out.println("2");
}
public void dip2(){
System.out.println("4");
}
}
//输出
1
1
1
4
foo
bar
foo
foo
foo
(Base)s : getClassName = com.code.Sub如果是类变量或者类方法父类引用指向子类对象是不会发生动态绑定的,实例方法才会出现运行时多态,getClass()是实例方法,所以会执行子类的getClass();,当然前提是父类要有这个方法
父类的引用指向子类的对象,我承认说反了,但你说upcasting不是多态的表现?Luca Cardelli和Peter Wegner将多态分为两大类—-特定的和通用的—-四小类:强制的,重载的,参数的和包含的。其中包含的就包括向上转型
好像一个效果,我刚刚试了下
public class Base{
public void dip(){
System.out.println("3");
}
public static void main(String []arg){
Base b = new Base();
Base b2 = new Sub();
Sub s = new Sub();
b.dip();
b2.dip();
s.dip();
}
}
class Sub extends Base{
public void dip(){
System.out.println("4");
}
}
//输出
3
4
4
class A {
public void f() {
System.out.println("A");
}
}class B extends A {
public void f() {
System.out.println("B");
}
}Public class Test {
public static void main(String arg[]) {
B b = new B();
b.f();
((A)b).f();
}
}这就是向上转型时体现的多态!
够别扭的,你这个例子感觉就是为了多态而upcasting
再看看另一位同志的原话多态怎么也是要动态调用子类的方法吧,
这个扯到调用静态变量不说,调用的还是父类的变量,
讲难听点就是乱搞upcasting和多态,看到upcasting和貌似的多态就瞎搅在一起
搞得我更乱了!!!我只是不明白为什么A处是输foo(现在还是没明白,恕愚钝,望路过的哥哥姐姐们给个明白的解释,),没料到竟然引来口舌之争,罪过罪过
谢谢
那是class A的东西,是静态变量
只有method才有override,才有多态的概念,
既然强制转换成了A类型的,当然调A.FOO