老题重谈 静态属性和方法的继承

loveajin 2011-11-02 09:38:08
前不久写一个东东,因设计不当,用到了这块内容,也上网搜索了很多资料,感觉还是不够清晰。望高手、专家踊跃参与讨论。看谁能让大家信服。
题:静态属性和方法能否被继承?是如何继承的?

class base{
protected static String p="123";
public static String getP(){return p;}
public static void setP(String a){p=a;}
public static String test(){return p+"test";}
}
class sub extends base{
private static String p="abc";
//public static String getP(){return p;}
}

class test{
public static void main(String[] a){
//base.setP("123");
//sub.setP("abc");
System.out.println(base.getP());
System.out.println(sub.getP());
}
}

请就题而论,给一个清晰的解释,谢谢!
...全文
270 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
loveajin 2011-11-02
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 jj_magical 的回复:]

尽量命名要规范,子类和父类的属性和方法也最好不要同名,就不会出现这种问题了,最好换种方式写!
[/Quote]
敢不敢看清题目再发言……
孤单旅行 2011-11-02
  • 打赏
  • 举报
回复
尽量命名要规范,子类和父类的属性和方法也最好不要同名,就不会出现这种问题了,最好换种方式写!
dntg007 2011-11-02
  • 打赏
  • 举报
回复
对于继承而言,静态和非静态我认为是一样的。只不过多了一些可选的使用方式而已。
良才2015 2011-11-02
  • 打赏
  • 举报
回复
System.out.println(base.getP());-----很明显执行的是base中的getP(),得到base中的p(“123”)
System.out.println(sub.getP());-------sub中没有getP()方法,将会调用base中的getP(),得到base中的p(“123”)
所以打印出来都是123
但是,如果public static String getP(){return p;}不注释掉,System.out.println(sub.getP());将会调用sub中的getP()

loveajin 2011-11-02
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 dntg007 的回复:]

8楼
首先,你的想法是在子类中新建一个变量。而需要父类的方法能使用它。那么如果这个变量是新定义的,父类的方法根本无法确定,也就无法超作。这没有任何问题吧。
现在关键是你在子类中只是定义了一个父类中存在的同名变量而已。如果你不重新定义,而是使用父类定义的变量,那应该没有问题吧。现在你既然要重新定义,就是想区别于父类的。这和定义了一个新的变量没有什么区别。父类的方法为什么要可以超作它呢。
[/Quote]
我明白你的意思,我们不跑题,现在就是针对静态属性和方法的继承而讨论,你说的对,所以我说对于静态属性和方法,继承是没有意义的。当然,除了工具类,比如静态方法不对属性控制。
dntg007 2011-11-02
  • 打赏
  • 举报
回复
8楼
首先,你的想法是在子类中新建一个变量。而需要父类的方法能使用它。那么如果这个变量是新定义的,父类的方法根本无法确定,也就无法超作。这没有任何问题吧。
现在关键是你在子类中只是定义了一个父类中存在的同名变量而已。如果你不重新定义,而是使用父类定义的变量,那应该没有问题吧。现在你既然要重新定义,就是想区别于父类的。这和定义了一个新的变量没有什么区别。父类的方法为什么要可以超作它呢。
loveajin 2011-11-02
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 dntg007 的回复:]

这里关键是p这个变量,指的是this.p,所以父类的使用的p,就是父类的p,子类中使用的p就是子类中定义的p,如果子类想使用父类的变量,应该可以用super.p来获取。方法也是一样。
调用子类的方法时,如果子类自己定义了,就是用自己的,如果没定义,就使用父类的。而方法中使用的变量如果在方法对应的类中定义了,就使用本类的变量,如果没定义,就是用父类的变量。
[/Quote]
还是以贴的代码为例子。在sub2中没定义get和set方法,那么在test类中,调用sub2.getP()的时候就应该是调用了base.getP(),而base.getP()就应该得到base的p属性。现在反过来思考,如果我想通过sub2.getP()获取到sub2的p属性,那么就需要在sub2中定义getP方法,那继承岂不是没用,对于静态属性和方法,继承岂不是没意义?
dntg007 2011-11-02
  • 打赏
  • 举报
回复
这里关键是p这个变量,指的是this.p,所以父类的使用的p,就是父类的p,子类中使用的p就是子类中定义的p,如果子类想使用父类的变量,应该可以用super.p来获取。方法也是一样。
调用子类的方法时,如果子类自己定义了,就是用自己的,如果没定义,就使用父类的。而方法中使用的变量如果在方法对应的类中定义了,就使用本类的变量,如果没定义,就是用父类的变量。
小菜鸟的博客 2011-11-02
  • 打赏
  • 举报
回复
我指说一句 静态方法 静态变量 不能被继承
loveajin 2011-11-02
  • 打赏
  • 举报
回复
谢谢楼上的哥,关于命名规范平时都还是很遵守的 :),这个是用来测试就随便写写了。其实也不是去钻那些灰色语法,只是恰巧遇到了。还是你说的对,static的方法一般是工具类,一般不继承。而这个问题其实也就是想弄明白自己对静态属性和方法的继承是否理解有误,如果弄不明白那只能在今后不这么做,但却又担心哪天会遇到。有点矛盾又有点尴尬……呵呵
风尘中国 2011-11-02
  • 打赏
  • 举报
回复
我没有运行你这个代码,只是用眼看了一下,提醒你Java命名规范类名首字母大写

还是我那句话,static的方法一般都是工具类方法,调用的时候都是用 类名.方法名调用,而且一般都不好在

static的属性和方法上进行继承,至于你说的“伪继承”是个人理解吧,知道怎么调用,怎么是正确的方法就

OK了,没必要钻一些平时根本不太用得着的灰色语法范畴

[Quote=引用 3 楼 loveajin 的回复:]

引用 2 楼 ioe_gaoyong 的回复:

静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成的,不需继承机制就可以调用
如果子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为“隐藏”

你如果想要调用父类的静态方法和属性,直接通过父类名.方法名或变量名 完成

至于是否继承一说,子类是有继承静态方法和属性,但是跟实例方法和属性不太一样,存在“隐藏”……
[/Quote]
loveajin 2011-11-02
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 ioe_gaoyong 的回复:]

静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成的,不需继承机制就可以调用
如果子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为“隐藏”

你如果想要调用父类的静态方法和属性,直接通过父类名.方法名或变量名 完成

至于是否继承一说,子类是有继承静态方法和属性,但是跟实例方法和属性不太一样,存在“隐藏”的这种情况
[/Quote]

class base{
protected static String p="123";
public static String getP(){return p;}
public static void setP(String a){p=a;}
}
class sub1 extends base{//将继承base类所有可继承的属性和方法,类毫无意义}
class sub2 extends base{
private static String p="abc";
//public static String getP(){return p;}
//定义自己的p属性,这个属性和父类base的p属性毫无关系。
/**
* 继承了所有base类的可继承的不包含p的属性和方法。问题在这里:
* 1.首先可以肯定有getP和setP方法,但这两个方法操作的P却不知道是base的还是sub2的。
* 2.如果定义了自己的getP和serP方法,将隐藏base的get和set方法。那么sub2和base都有自己的set和get方法。
* 3.在外面调用时,用 "类名.可访问方法或属性" 来访问(调用)属性(方法)。类似第一点,如果静态属性是外面无法访问的,而提供一个外面可访问的方法去操作属性,那么继承并没有起到预想的效果。
*
* 综合前面,是否可以这样说,静态属性和方法能继承,但应该称之为"伪继承"。这种继承没有意义??
*/
}

class test{
public static void main(String[] a){
//base.setP("123");
//sub.setP("abc");
System.out.println(base.getP());
System.out.println(sub.getP());
}
}
风尘中国 2011-11-02
  • 打赏
  • 举报
回复
静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成的,不需继承机制就可以调用
如果子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为“隐藏”

你如果想要调用父类的静态方法和属性,直接通过父类名.方法名或变量名 完成

至于是否继承一说,子类是有继承静态方法和属性,但是跟实例方法和属性不太一样,存在“隐藏”的这种情况
xierong2011 2011-11-02
  • 打赏
  • 举报
回复
打印只能是123 123
父类赋值后子类只能继承不能重新赋值

class sub extends base{
private static String p="abc";
public static String getP(){return p;}
}

你要是改成这样 可以打印出123 abc 但是相当于子类重新定义了一个字段方法而已 并非全部继承而来的
liujun3512159 2011-11-02
  • 打赏
  • 举报
回复
帮忙顶下,呵呵
ganhuihuikukuku 2011-11-02
  • 打赏
  • 举报
回复
我没有运行 自己认为输出的应该是"123" 和"123"
就代码而言 有疑问的地方估计在sub.getP() 这里.
因为子类没有重写getP()方法 .So 调用的还是父类的getP() 输出的自然也是"123"了
父类里虽然定义了p变量 是private 修饰的 这样和父类的p变量也没有构成属性重写
因为子类重写必须要比父类权限要大 即使修饰符改成public 了 也输出的"123"
因为在sub.getP()里实现的是super.p 要是重写了getP()结果就不一样的 .
..... 我说错了 希望指出来 .谢谢 !
龙腾冰 2011-11-02
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 magong 的回复:]

这个涉及到方法和属性的寻址。也涉及到对象和类的空间分配。
关于寻址(或者说绑定):
从某代码发起的一次访问请求(代码所在的源和代码访问的目标有可能是同一个类或对象,也有可能不是):
①子类中找不到的方法和属性,到父类找,不管是静态还是动态。
②不写前缀(或写this)时从本对象所属的子类(可能比本类层次低)开始找方法。如果用类名(静态方法情况下)或用super指定了目标类,则从该目标类开……
[/Quote]
这位仁兄分析的很好
桃园闲人 2011-11-02
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 magong 的回复:]

这个涉及到方法和属性的寻址。也涉及到对象和类的空间分配。
关于寻址(或者说绑定):
从某代码发起的一次访问请求(代码所在的源和代码访问的目标有可能是同一个类或对象,也有可能不是):
①子类中找不到的方法和属性,到父类找,不管是静态还是动态。
②不写前缀(或写this)时从本对象所属的子类(可能比本类层次低)开始找方法。如果用类名(静态方法情况下)或用super指定了目标类,则从该目标类开……
[/Quote]

这位仁兄回答的非常完美。
Antineutrino 2011-11-02
  • 打赏
  • 举报
回复
回到楼主的问题上来
Sun把方法的继承称为重写或覆盖(Override),与之对应的是重载(Overload),相信这两个概念一般人都很熟悉了。
重载很简单,通过方法的“签名”来实现,是编译器静态行为,没什么多说的。
那么重写呢?重写发生在继承的过程中。重写方法的调用是在运行期间动态进行的,这种方式称为动态绑定。在Java中,重写方法的这种动态性很彻底,你无法在使用子类时调用被重写的父类方法(除非由子类自己显式调用),Java强制将调用绑定到子类上。
而实例域则没有重写(或继承)的概念。它们的访问控制符(public、protected、package或private)仅仅决定该实例域的可见性,而与继承无关。这与局部变量隐藏实例变量的概念是类似的,不属于继承的范畴。
下面的例子中SubBook继承Book,它们都定义了一个同名的int型变量
Book b1 = new Book();
Book b2 = new SubBook();
SubBook b3 = (SubBook) b2;
SubBook b4 = new SubBook();
打印b1~b4的变量的值,发现b1和b2访问的是父类中的变量、b3和b4访问的是子类中的变量。也就是说,实例域的访问与实际类型无关,而只取决于此实例当前被赋予的类型,可以认为这也是一种编译器静态行为。

静态属性和静态方法与实例域是非常相似的,没有继承的概念,都是编译器的静态行为。
Antineutrino 2011-11-02
  • 打赏
  • 举报
回复
关于这种底层机制问题,下狠功夫研究吧,好像用处不大,还要花费大量的时间和精力,不研究吧,到真遇到一些莫名其妙的问题的时候又会傻眼
难啊,越来越感觉真的是学无止境
加载更多回复(4)

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧