现在我也只是死记住 这是多态。当a调用变量时候就是调用父类,调用方法就是子类...

继承那个还是有点不太明白。。。唉。。。。


这题我还是不是太明白。。。比如

class A
{
int x=100;
void output()
{
System.out.println("class A");
}

}

class B extends A
{
int x=1000;

void output()
{
System.out.println("class B");
}
public static void main(String[] args)
{
A a=new B();
System.out.println(a.x);
a.output();
}
}

现在我也只是死记住 这是多态。当a调用变量时候就是调用父类,调用方法就是子类,可是还是不明白为什么。。

这句话 A a=new B(); 编译过程是怎么样的。听说编译时候编译器只看A a前面?然后下面,System.out.println(a.x);中就自动将a.x指向父类的。
那怎么一调用方法,a.output(); 就自动指向子类方法去了?
虽然硬记住了这个规律,但概念还是不懂。。麻烦各位讲讲。

谢谢




回复人:xuxinjie 回复时间:2005-9-24 13:41:00
这问题好难,我也糊涂了,请大家帮忙

回复人:橙色稀饭 回复时间:2005-9-24 14:11:00
发表一下个人意见
这道题是有关java中的三大特性之一:多态
由于b类继承a类所以在内存开辟的范围比父类大,只能写成 A a=new B();若写成
B b = new A();应该产生所谓的“溢出”这是java所不允许的。
而父类的引用只能访问到父类的那个区域,但方法覆盖就例外了,访问的是覆盖后的方法


回复人:jkluooop 回复时间:2005-9-24 15:38:00
B继承A,并重新定义了A的x域与output()方法,虽然形式一样,内里不一样,
B重写x,它继承来的A.x依然存在,只是被B.x隐藏了,A.x在B中依然占有自己的内存空间,可以在B中用super.x访问。而重写output(),此时B.output()将覆盖继承来的A.output(),清除A.output()在B中占用的内存空间,从而使A的同名方法在子类对象中不在存在。
Java中类型转换发生在具有继承关系的类之间,子类可以看做是父类的一种特殊类型,在做类型转换时,子类对象可以直接赋予父类,A a=new B();就做了这样一件事情
编译器上溯到A,去掉了B.x;(信息丢失,因为A不需要B的特有物)将一个方法调用同一个方法主体连接到一起就称为“绑定”,在程序运行时才确定该执行哪个方法主体的叫“动态绑定”,Java中绑定的所有方法都采用动态(后期)绑定技术,Java里绑定的所有方法都通过动态绑定具有多形性。A a=new B();执行后,a.output()调用的方法主体是B.output(),因为后期绑定已经介入(发生在类机制回溯过程).
楼主一个小问题牵扯出了大东西,偶也不是很清晰,这牵扯到java编译器的内部运行机制,建议楼主去看看Thinking in Java,那里讲的比较清楚



回复人:DeathHeart 回复时间:2005-9-24 16:41:00
感谢大家的解答:)

回复人:leaonow 回复时间:2005-9-24 16:56:00

其实可以这样理解~就用楼主的例子,想想看,如果你把a,b实名化,a可以看成汽车,b是一种汽车,比如说马自达的Ms8房车,
那么a a1 = new b();可以理解为ms8是汽车的一种
假设我们有b b1 = new a() [这是错误的!但我们假设他成立],那么我们可以得到一个荒谬的结论,所有的车都是ms8.
另外你提到“那怎么一调用方法,a.output(); 就自动指向子类方法去了?”
你可以这样理解,如果你开的是一辆火车,(这个例子不太合适,但是我们假设火车是汽车的一种,厚厚,自欺欺人),那么你想,所有汽车都有一个method,叫“刹车”,如果你不调用火车本身的刹车方法,而调用夏利的刹车方法,那么可想而知。。。这里我为什么说夏利呢而不说a(汽车)通用的刹车方法呢?因为车有不同,刹车方法也不同,所以父类一般来说不会把方法实例化,很可能只是
public void break(Object obj) {
}
表示一下而已,也就是不刹车,你总不想看到你的火车冲出去吧~,或者调用夏利车的刹车方法,这样估计火车也要冲出去百十公里才能停住吧~
希望能帮到你


CSDN网友 dracularking 写道:

若没看错 楼主说的这种情况应该是隐藏(hidden) 翻译区别于覆盖,因为容易与override混淆

子类对父类的继承可能导致各种陷阱,比如隐藏(hidden),遮蔽(shadow),遮掩(obscure),覆写(override),重载(overload)等行为。

来看看2个隐藏的例子:

1.

Java代码
class Base {
public String className = "Base";
}

class Derived extends Base {
private String className = "Derived";
}

public class PrivateMatter {
public static void main(String[] args) {
System.out.println(new Derived().className);
}
}

class Base {
public String className = "Base";
}

class Derived extends Base {
private String className = "Derived";
}

public class PrivateMatter {
public static void main(String[] args) {
System.out.println(new Derived().className);
}
}


我们可能指望它打印Base,可很抱歉,此程序是无法编译通过,刚一看错误信息你可能愣住:

无权访问private的className。。。

对于实例方法,子类可以对父类的实例方法进行覆写,可对于实例变量(而且包括类变量,静态方法,final静态变量),子类只能隐藏父类中的相同名称的变量,而不是覆写。根据new Derived()的编译期类型为子类Derived,调用子类的className属性,可此属性是声明为private的,所以无法编译通过。如果我们想调用父类中被隐藏的className,可以通过向上转型来实现:

Java代码
System.out.println(((Base)new Derived()).className);

System.out.println(((Base)new Derived()).className);

此例告诉我们,JAVA语言中子类定义与父类相同类型和名称的变量、嵌套类型和静态方法,都将隐藏掉父类中相应的方法,而不是覆写,所以,请避免隐藏!此过程中当然也不存在所谓多态。另外,我们不应该违反这样一条规则:对基类所做的任何行为,都应当可以同样作用于子类。此例中子类className为private,违反了基类中className是public的定义,这样的写法应该避免。

2.也许哪一天你突然想自己写一个String来代替java.lang中的String,让我们来看看会发生什么?

Java代码
public class StrungOut {
public static void main(String[] args) {
String s = new String("Hello world");
System.out.println(s);
}
}

class String {
private final java.lang.String s;

public String(java.lang.String s) {
this.s = s;
}

public java.lang.String toString() {
return s;
}
}

public class StrungOut {
public static void main(String[] args) {
String s = new String("Hello world");
System.out.println(s);
}
}

class String {
private final java.lang.String s;

public String(java.lang.String s) {
this.s = s;
}

public java.lang.String toString() {
return s;
}
}

试运行此程序,JVM会给你一个非常奇怪的消息:

StrungOut does not have a main method!

怪了,明明有个main方法啊??请注意,main方法中的参数String []args,其中的String类型要求是java.lang.String,可JVM会自动地把把这些参数认为是我们自定义的下面那个String类型,这就是错误的原因所在。教训:避免重用类名,特别是java平台的类型,特别是java.lang包下的类名!在此例中,当前类所在包中的所有类的main方法都将因此失效。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值