前不久写一个东东,因设计不当,用到了这块内容,也上网搜索了很多资料,感觉还是不够清晰。望高手、专家踊跃参与讨论。看谁能让大家信服。
题:静态属性和方法能否被继承?是如何继承的?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());
}
}请就题而论,给一个清晰的解释,谢谢!
题:静态属性和方法能否被继承?是如何继承的?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());
}
}请就题而论,给一个清晰的解释,谢谢!
父类赋值后子类只能继承不能重新赋值class sub extends base{
private static String p="abc";
public static String getP(){return p;}
}你要是改成这样 可以打印出123 abc 但是相当于子类重新定义了一个字段方法而已 并非全部继承而来的
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());
}
}
调用子类的方法时,如果子类自己定义了,就是用自己的,如果没定义,就使用父类的。而方法中使用的变量如果在方法对应的类中定义了,就使用本类的变量,如果没定义,就是用父类的变量。
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()
关于寻址(或者说绑定):
从某代码发起的一次访问请求(代码所在的源和代码访问的目标有可能是同一个类或对象,也有可能不是):
①子类中找不到的方法和属性,到父类找,不管是静态还是动态。
②不写前缀(或写this)时从本对象所属的子类(可能比本类层次低)开始找方法。如果用类名(静态方法情况下)或用super指定了目标类,则从该目标类开始找方法。
③不写前缀(或写this)时从本代码所属的类开始找属性,如果用类名(静态方法情况下)或用super指定了目标类,则从该目标类开始找属性。关于空间分配:
①每个类的static属性及所有的方法放类自己的空间中。
②每个类的非static属性放对象中。
③子类对象包含父类对象,也就是说,子类对象创建的时候,会为所有的父类属性分配空间。父类代码发起的对父类非静态属性的访问,最终访问的是子类对象空间中的父类属性。好,开始分析楼主顶楼的代码:
base.getP();直接找到父类的getP()方法,getP()方法中return p返回父类中的p属性值,123
接着执行
sub.getP();子类没有该方法,往上找,依然找到父类的getP()方法,getP()方法依然return p返回父类中的p属性值,123问题复杂,有不明白的地方,继续讨论。
当然static的方法 它操作它方法体中指定的static的那个数据继承了base 子类就继承了 访问和修改base共享数据的能力
当你屏蔽掉了访问和修改的能力 继承来的增强功能都被屏蔽了
显然没有继承来任何东西,继承也就显得多余了
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访问的是子类中的变量。也就是说,实例域的访问与实际类型无关,而只取决于此实例当前被赋予的类型,可以认为这也是一种编译器静态行为。静态属性和静态方法与实例域是非常相似的,没有继承的概念,都是编译器的静态行为。
就代码而言 有疑问的地方估计在sub.getP() 这里.
因为子类没有重写getP()方法 .So 调用的还是父类的getP() 输出的自然也是"123"了
父类里虽然定义了p变量 是private 修饰的 这样和父类的p变量也没有构成属性重写
因为子类重写必须要比父类权限要大 即使修饰符改成public 了 也输出的"123"
因为在sub.getP()里实现的是super.p 要是重写了getP()结果就不一样的 .
..... 我说错了 希望指出来 .谢谢 !