0 0

java子类继承父类问题10

java子类继承父类问题
求解释! 虽然做了几年的开发
但确实不明白为什么?
class Foo {
 public int a;
 public Foo() { a = 3; }
 public void addFive() { a += 5; }
}

public class Bar extends Foo{
    public int a;
    public Bar() { a = 8; }
    public void addFive() { this.a +=5; }
    
    public static void main(String[] args) {
        Foo foo = new Bar();
         foo.addFive();
         System.out.println("Value: "+ foo.a);
    }

}



结果为什么输出的是3
可以试下~
求解释

问题补充:
看到楼下的很多朋友的回答
我之前也是这么认为的
与java得多态有关 方法可以多态重载,但属性不能

假设这样设想 我想得到结果是
在父类的属性a的值的基础上 让其用子类的加法进行呢?

如何实现呢?
public int addFive() {
  super.a += 5;
}

就可以了
OO 
2009年9月11日 19:51

22个答案 按时间排序 按投票排序

0 0

采纳的答案

class Foo {
	public int a;

	public Foo() {
		a = 3;
	}

	public int addFive() {
		a += 5;
		return a;
	}

	public int getA() {
		return a;
	}
}

public class Bar extends Foo {
	public int a;

	public Bar() {
		a = 8;
	}

	public int addFive() {
		this.a += 5;
		return a;
	}

	public int getA() {
		return a;
	}

	public static void main(String[] args) {
		Foo foo = new Bar();
		//调用的是子类中的方法
		System.out.println(foo.getA());
		//直接调用父类中的a
		System.out.println("Value: " + foo.a);
		//调用的是子类中的方法
		System.out.println(foo.addFive());
		
	}
}
输出结果:
8
Value: 3
13


楼主,只需要明白一点就行了:在Java中重写指的是方法的重写,而不是属性的重写,还有多态也只是方法的多态 ,没有属性的多态。





2009年9月14日 09:25
0 0

class Base{ 
   public int a; 
   public static int b; 
   public Base(){ 
     a=1; 
     b=1; 
   } 
   public void addFivetoa(){ 
    a+=5; 
   } 
   public static void addSixtob(){ 
    b+=6; 
   } 

public class Son extends Base{ 
  //public int a; 
  //public static int b; 
  public Son(){ 
   a=2; 
   b=2; 
  } 
public void addFivetoa(){ 
   a+=5; 
  } 
public static void addSixtob(){ 
   b+=6; 

public static void main(String args[]){ 
Son son = new Son(); 
Base base = son; 
base.addFivetoa(); 
base.addSixtob(); 
System.out.println(base.a);//7 
System.out.println(base.b);//8 
System.out.println(son.a);//7 
System.out.println(son.b);//8 



过程:先初始化Base的b为0,然后调用父类的构造方法初始化a=1,b=1,然后调用Son的构造方法初始化a=2,b=2;
base.addFivetoa();//a=7;调用的子类的
base.addSixtob();//b=8;调用的父类的
属性是不能多态的,静态方法也不能多态。
图示:
[img] http://dl.iteye.com/upload/attachment/146753/1c112269-254f-3f9e-9bd4-afa547d99cd3.jpg[/img]

衍生:
Java代码
class Base{ 
   public int a; 
   public static int b; 
   public Base(){ 
     a=1; 
     b=1; 
   } 
   public void addFivetoa(){ 
    a+=5; 
   } 
   public static void addSixtob(){ 
    b+=6; 
   } 

public class Son extends Base{ 
  public int a; 
  public static int b; 
  public Son(){ 
   a=2; 
   b=2; 
  } 
public void addFivetoa(){ 
   a+=5; 
  } 
public static void addSixtob(){ 
   b+=6; 

public static void main(String args[]){ 
Son son = new Son(); 
Base base = son; 
base.addFivetoa(); 
base.addSixtob(); 
System.out.println(base.a);//1 
System.out.println(base.b);//7 
System.out.println(son.a);//7 
System.out.println(son.b);//2 




过程:先初始化Base的b为0,然后调用父类的构造方法初始化a=1,b=1,然后调用Son的构造方法初始化子类中的a和b,a=2,b=2;
base.addFivetoa();//调用子类的方法,son.a=7
base.addSixtob();//调用父类的方法,base.b=1+6=7
剩下的base.a和son.b都没有变化所以分别为1,2。
其中加粗红色的1是父类的b的值,base.addSixtob()(是静态的)所以要调用addSixtob()所在类base的b的值也就是,或者说是base对象调用了addSixtob(),所以要访问base对象所在类的b值。
图示:

2009年9月18日 17:48
0 0

Foo foo = new Bar();
就相当于Foo foo = new Foo();没什么区别!!

2009年9月18日 17:11
0 0

受教了,好好学习。

2009年9月18日 16:16
0 0

不好意思,说错了。谢谢上面的纠正

2009年9月18日 10:32
0 0

引用
Foo foo = new Bar();     此时,new的虽然是Bar()的实力,但是在内存看到的只是父类的方法跟属性,与子类无关。所以,a的值为3。

子类的方法,父类的属性

2009年9月18日 10:25
0 0

Foo foo = new Bar();     此时,new的虽然是Bar()的实力,但是在内存看到的只是父类的方法跟属性,与子类无关。所以,a的值为3。

2009年9月18日 10:23
0 0

Foo foo = new Bar();    //foo.a=3,bar.a=8
foo.addFive();          //bar.a=8+5
System.out.println("Value: "+ foo.a);  //foo.a=3,bar.a=13

这也是隐藏域,提供setter/getter的一个原因吧。

2009年9月17日 15:29
0 0

父类中的a和子类中的a是两个不同的成员变量,同时存在的,不会出现覆盖的现象。
Foo foo = new TestEYE1();  //调用父类构造。
此时,foo虽然是TestEYE1,但是它是被当作Foo来执行的。
所以它的一些TestEYE1属性全部都被禁用。但是堆中存在这些属性。
当调用
foo.addFive();   方法时,由于子类对父类的方法重写,执行子类的方法,
this.a +=5;  其中this可以不加的,默认的就是调用本类(TestEYE1)的成员变量。

最后打印foo.a,foo虽然有两个a成员变量,但是因为它现在是Foo身份,所以子类的a是禁用的,但是它还是存在的,只要身份变成TestEYE1,就会打印子类的a属性。看第二次打印的结果就知道了。
System.out.println("Value: "+ foo.a);  
System.out.println("Value: "+ ((TestEYE1)foo).a);  

这个题目,如果楼主觉得混要,有一个简单的方法,把子类的a全改成b,就知道了。
因为对计算机而言,这两个成员变量就算是名字相同,它也认为不同的。
只要明白,这两个成员变量都存在就好理解了~

2009年9月16日 13:43
0 0

分析得都很好,学习了

2009年9月16日 09:55
0 0

是的,分析得很好呢.......

2009年9月15日 09:25
0 0

注意:这句  Foo foo = new Bar();创建了一个Bar对象
一个对象创建的过程分成4步:
1.分配空间
2.递归创建父类对象
3.调用本类构造方法 
4.初始化本类属性;
还有第2点 其实是创建了父类的属性和方法,并没有创建父类对象,用人们的眼光来把它
单独拿出来看,是创建了父类对象似的;
父类的除private方法以外的方法都被子类所继承.并且覆盖但是属性却没有被覆盖,所以foo.a  访问的是父类的 属性,而 foo.addFive(); 调用的是子类覆盖父类的 addFive()方法,既然调用的是子类的方法,所以这个方法修改的是子类属性的值


2009年9月14日 22:03
0 0

楼上回答的很棒,方法是重写,属性不能重写。

2009年9月14日 11:16
0 0

呵呵,虽然知道子类能override方法,不能override属性,但还是没做出来,羞愧。

2009年9月14日 00:04
0 0

引用
有点值得关注的是。如果addFive返回类型改成int 之后
你打印System.out.println(foo.addFive());  
的值是18,而不是13。

晕。。我用了两次 foo.addFive(); 怪不得是18.
晕到我。 

2009年9月13日 13:41
0 0

其实去看Debug View的内存树会比较清楚。。。。

2009年9月12日 20:32
0 0

在子类中调用父类同名属性可以这样写super.a

2009年9月12日 14:27
0 0

主要的问题是你要理解子类重写父类方法会造成父类方法被覆盖,而属性却不是这样;
          Foo foo = new Bar();
程序运行到这一部,是实例化一个子类对象交给父类引用,在这个对象中有两个属性a,父类的属性a=3和子类自己的a=8  ,而addFive方法只有一个,那就是子类重写的addFive方法;
         foo.addFive(); 
这一步调用的是子类重写后的方法,所以在这里值发生改变的是子类的a而不是父类的,这时候子类的a=8+5=13,而父类的a=3没有变。
         System.out.println("Value: "+ foo.a);
foo是一个父类的引用,foo.a是父类的a当然是等于3了 

2009年9月12日 14:25
0 0

Foo foo = new Bar();  
像这种upcast(向上造型)
1.域:调用父类属性
2.方法:调用子类方法
这里 foo.addFive();   调用子类的方法
有点值得关注的是。如果addFive返回类型改成int 之后
你打印System.out.println(foo.addFive());  
的值是18,而不是13。
至于输出的是3
就是因为第一条,调用的是父类的属性。而跟方法无关。

引用
详情见:thinking in java 4th 的例子
中文版156
英文版290

2009年9月12日 12:25
0 0

Foo foo = new Bar();  //实际上实例化Foo 类中的a = 3;
foo.addFive();  //实际上调用了Bar类的方法

如果是想得到 5 + 8 = 13的结果,就封装a字段

class Foo {
private int a;
public Foo() { a = 3; }
public void addFive() { a += 5; }
public int getA() {
return a;
}

}

public class Bar extends Foo{
    private int a;
    public Bar() { a = 8; }
   
    public int getA() {
return a;
}

@Override
    public void addFive() { a +=5; }
   
    public static void main(String[] args) {
        Foo foo = new Bar();
        foo.addFive();
        System.out.println("Value: "+ foo.getA());
    }

}

2009年9月12日 09:12
0 0

这个是java类初始化问题,每个子类对象都含有父类对象,所以要先调用父类的构造函数构造一个父类对象。
你可以看看:Java类初始化顺序
http://red-xie.iteye.com/admin/blogs/258789

2009年9月12日 00:41
0 0

子类实例化的时候会调用它父类的默认构造方法

2009年9月11日 23:39

相关推荐

    java子类继承父类实例-披萨的选择实现代码

    Java子类继承父类实例-披萨的选择实现代码 本篇文章主要介绍了Java子类继承父类实例-披萨的选择实现代码,通过编写程序实现比萨制作,选择需要制作的比萨。可供选择的比萨有:培根比萨和海鲜比萨。下面是相关知识点...

    java 子类对象赋值给父类对象的使用

    在Java编程语言中,子类继承父类是一种常见的特性,它允许子类扩展或复用父类的功能。当我们创建一个子类对象并将其赋值给父类引用时,这种行为被称为向上转型(Upcasting)。这一过程是自动且安全的,因为子类对象...

    JAVA 子类继承父类的范例 可直接运行

    在Java中,继承是面向对象编程的核心特征之一,它允许我们创建一个新类(子类)基于一个已经存在的类(父类或超类)的结构。这样可以复用现有类的代码,并可添加或覆盖特性来形成新的类。本文将通过具体的代码范例,...

    java子类重写父类的方法.doc

    Java 子类重写父类的方法详细解析 Java 中子类重写父类的方法是面向对象编程的核心概念之一。子类可以重写父类的方法,以改变或扩展父类的行为。但是,子类重写父类的方法需要遵守一定的规则,以避免编译器错误和...

    java中的继承(子类调用父类构造方法还不懂).doc

    在 Java 中,使用 `extends` 关键字可以实现继承关系,子类可以继承父类的属性和方法,并可以重写父类的方法。使用 `super` 关键字可以引用父类的成分,访问父类中定义的属性和方法。 在 Java 中,可以使用多态性来...

    继承的小例子

    当一个子类继承一个父类时,子类就自动获得了父类的所有非私有(public和protected)成员,包括字段和方法。这使得子类能够共享父类的功能,同时还可以添加自己的特性和行为。通过关键字`extends`,我们可以声明一个...

    将子类引用赋给父类对象时,java虚拟主机并没有将那些非继承成员丢弃

    子类B不仅可以继承父类A的所有公有(public)和受保护(protected)成员,还可以有自己的特有成员。当我们声明一个父类类型的引用并将其赋值为子类的对象时,如`Car car = new SportsCar();`,这里的`car`引用虽然...

    论JAVA继承机制中父类与子类的关系

    文章围绕子类继承父类成员的过程、成员变量及方法的赋值、重写、覆盖等问题展开讨论,旨在帮助读者更好地理解Java继承中的重点与难点。 #### 关键词 - 继承机制 - 父类 - 子类 #### 一、超类的属性或方法在继承...

    java反射获取所有属性,获取所有get方法,包括子类父类

    总结,Java反射机制为我们提供了强大的动态性,能够方便地获取和操作类的属性和方法,包括私有成员和子类父类中的成员。通过熟练掌握反射技术,开发者可以实现更灵活、更动态的代码,但也需要谨慎使用,以避免潜在的...

    再次详细说明在继承中的程序执行顺序,子类与父类到底哪个先执行

    本文将深入探讨在继承中的程序执行顺序,以及子类与父类的执行顺序问题。 首先,我们需要了解Java或Python等面向对象语言中类的构造过程。当一个类实例化时,其构造函数(在Java中是`构造器`,在Python中是`__init_...

    java子类调用父类的方法中包含子类重写的实例方法

    Java子类调用父类的方法中包含子类重写的实例方法 Java 子类调用父类的方法中包含子类重写的实例方法是 Java 编程语言中一个重要的概念。下面我们将详细介绍这个概念,包括相关的知识点和示例代码。 子类调用父类...

    Java编程关于子类重写父类方法问题的理解

    Java编程关于子类重写父类方法问题的理解 Java编程中,子类重写父类方法是非常重要的概念之一。子类重新实现父类的方法称为重写,重写时可以修改访问权限修饰符和返回值,但方法名和参数类型及个数不能修改。只有...

    在父类获取子类属性

    这个主题涉及到面向对象编程的基本原理,特别是子类继承父类后如何访问和操作子类特有的属性。下面我们将深入探讨这个话题。 首先,我们了解基本的继承概念。在Java中,一个类(子类)可以继承另一个类(父类),...

    java判断class子类或父类的实例方法

    在本篇文章中,我们学习了如何使用 Java 中的反射机制来判断类的继承关系,包括判断一个类是否为基本数据类型、判断一个类是否为另一个类的子类或父类,以及如何获取泛型类型实例。这些技术在日常开发中非常实用,...

    java 类的继承 基础理解

    1. 代码重用:继承允许子类继承父类的属性和方法,从而减少代码的冗余和重复。 2. 继承关系建模:继承可以建模现实世界中的继承关系,如车辆的继承关系,即 Car 。 3. 提高代码的灵活性:继承允许子类继承父类的方法...

    Java父类继承代码示例

    在Java编程语言中,继承是面向对象编程的一个关键特性,它允许一个类(子类)继承另一个类(父类)的属性和方法。这有助于实现代码重用,并且可以创建层次结构的类系统,使代码更加模块化。下面我们将深入探讨Java中...

    Java子类的继承性

     如果子类和父类不在同一个包中,那么子类继承了父类的protected、public成员变量作为子类的成员变量,并且继承了父类的protected、public方法,继承的成员或方法的访问权限保持不变,但子类不能继承父类的友好...

Global site tag (gtag.js) - Google Analytics