java中的方法能重写,属性能重写吗?

覆写是多态的一种表现,我们平时所说的覆写一般是针对方式来说,在网上看到过有人讨论试着覆写属性,于是有点兴趣,属性真能覆写吗?回答问题之前,我们还是回忆一下方法的覆写具备哪些条件,或都说哪些方法能覆写。先回顾一下方法覆写要注意的地方:1、重载(也叫过载)时只与方法特征有关,但重写(覆写)是会进一步检查两个方法的返回类型是否相同、访问修饰权限是否缩小(假设public->protected方向是缩小,反之叫扩大)和抛出的异常范围是否扩大。那么什么是方式特征呢?一个方法的特征(也可叫方法签名)仅包括方法的名字、参数的个数、类型、顺序(实质上就是参数列表),而不包括方法的返回类型、访问修饰权限与所抛出的异常。

Java代码

    publicclassA{ publicvoidoverwrite(inti)throwsIOException{} } classBextendsA{ //!!编译通不过,不能缩小访问权限//voidoverwrite(inti)throwsIOException{}//!!编译通不过,不能扩大异常范围//publicvoidoverwrite(inti)throwsException{}//正常,编译没问题,可以不抛出异常//publicvoidoverwrite(inti){}//覆写父类方法 publicvoidoverwrite(inti)throwsIOException{} protectedvoidoverload(inti){} //重载上面的方法 intoverload(longi)throwsIOException{ return0; } }

[java] view plaincopy

    publicclassA{publicvoidoverwrite(inti)throwsIOException{}}classBextendsA{//!!编译通不过,不能缩小访问权限//voidoverwrite(inti)throwsIOException{}//!!编译通不过,不能扩大异常范围//publicvoidoverwrite(inti)throwsException{}//正常,编译没问题,可以不抛出异常//publicvoidoverwrite(inti){}//覆写父类方法publicvoidoverwrite(inti)throwsIOException{}protectedvoidoverload(inti){}//重载上面的方法intoverload(longi)throwsIOException{return0;}}

另外,要补充说明的是重载一般是指在同一个类中多个方法间,但也可重父类的的方法,而重写只发生面父子与子类的方法间。2、非私有非静态方法不能被任何静态方法覆写,如果子类中试着以静态方式(不管访问权限修饰符是什么)来覆写父类的方法,编译时会报错。

Java代码

    publicclassA{ voidf(){} } classBextendsA{ //!!编译出错,下面错误都一样//staticvoidf(){};//privatestaticvoidf(){};//protectedstaticvoidf(){};//publicstaticvoidf(){};}

[java] view plaincopy

    publicclassA{voidf(){}}classBextendsA{//!!编译出错,下面错误都一样//staticvoidf(){};//privatestaticvoidf(){};//protectedstaticvoidf(){};//publicstaticvoidf(){};}

3、非私有静态方法不能被任何非静态方法覆写,如果子类中试着以非静态方式(不管访问权限修饰符是什么)来覆写父类的方法,编译时会报错。

Java代码

    publicclassA{ publicstaticvoidf(){} } classBextendsA{ //!!编译出错,下面错误都一样//publicvoidf(){}//protectedvoidf(){}//voidf(){}//privatevoidf(){}}

[java] view plaincopy

    publicclassA{publicstaticvoidf(){}}classBextendsA{//!!编译出错,下面错误都一样//publicvoidf(){}//protectedvoidf(){}//voidf(){}//privatevoidf(){}}

4、子类与父类中有方法特征相同的静态方法时,覆写规则与非静态方法覆写规则一样,但一般我们不把静态方法的覆写叫覆写,虽然语法规则上与非静态方法相同。

Java代码

    publicclassA{ publicstaticvoidoverwrite(inti)throwsIOException{ System.out.println("父类静态方法…"); } } classBextendsA{ //!!编译通不过,不能缩小访问权限//staticvoidoverwrite(inti)throwsIOException{}//!!编译通不过,不能扩大异常范围//publicstaticvoidoverwrite(inti)throwsException{}//正常,编译没问题,可以不抛出异常//publicstaticvoidoverwrite(inti){}//覆写父类静态方法publicstaticvoidoverwrite(inti)throwsIOException{ System.out.println("子类静态方法…"); } publicstaticvoidmain(String[]args)throwsIOException{ Aa=newB(); //覆写静态在语法上是合法的,但没有多态效果a.overwrite(0);//print:父类静态方法…A.overwrite(0);//print:父类静态方法…B.overwrite(0);//print:子类静态方法…} }

[java] view plaincopy

    publicclassA{publicstaticvoidoverwrite(inti)throwsIOException{System.out.println("父类静态方法…");}}classBextendsA{//!!编译通不过,不能缩小访问权限//staticvoidoverwrite(inti)throwsIOException{}//!!编译通不过,不能扩大异常范围//publicstaticvoidoverwrite(inti)throwsException{}//正常,编译没问题,可以不抛出异常//publicstaticvoidoverwrite(inti){}//覆写父类静态方法publicstaticvoidoverwrite(inti)throwsIOException{System.out.println("子类静态方法…");}publicstaticvoidmain(String[]args)throwsIOException{Aa=newB();//覆写静态在语法上是合法的,但没有多态效果a.overwrite(0);//print:父类静态方法…A.overwrite(0);//print:父类静态方法…B.overwrite(0);//print:子类静态方法…}}

上面重写了父类的静态方法,但却没有多态作用,也就是说,静态方法不存在重写这一说,只不过在语法规则上与非静态方法一样罢了。5、私有方法对子类同名方法不产生任何影响,也就是说私有方法不能被重写,即使试着在子类覆写了父类的私有方法,不管访问权限修饰符是什么,在编译时也不会报错。原因就是私有方法对子类也是不可见的。

Java代码

    publicclassA{ privatevoidf(){ } //加上static修饰符,其结果都一样//privatestaticvoidf(){}} classBextendsA{ //尝试每个方式,都会编译能过//privatevoidf(){}//voidf(){}//protectedvoidf(){}//publicvoidf(){}//privatestaticvoidf(){}//staticvoidf(){}//protectedstaticvoidf(){}publicstaticvoidf(){} }

[java] view plaincopy

    publicclassA{privatevoidf(){}//加上static修饰符,其结果都一样//privatestaticvoidf(){}}classBextendsA{//尝试每个方式,都会编译能过//privatevoidf(){}//voidf(){}//protectedvoidf(){}//publicvoidf(){}//privatestaticvoidf(){}//staticvoidf(){}//protectedstaticvoidf(){}publicstaticvoidf(){}}

好了,上面总结并理解方法覆后,我们再来看属性能不能覆写,其实,这是一个很无聊的问题,不像上面讨论方法那有点价值,可以说属性是没有覆写这一说的,这有点像静态方法一样,不过还是稍微看一下:

Java代码

    publicclassA{ //这行不能去掉,否则①编译通不过inti=1; A(){ System.out.println("父类构造方法i="+this.i);//①this.f();//②System.out.println("父类中"+(this==getThis()));//③print:true} publicvoidf(){ System.out.println("父类方法f()i="+this.i); } publicAgetThis(){ System.out.println("父类getThis"); returnthis; } } classBextendsA{ inti=2; B(){ System.out.println("子类构造方法i="+this.i); System.out.println("子类中"+(this==super.getThis()));//④} publicvoidf(){ System.out.println("子类方法f()i="+this.i); } publicAgetThis(){ System.out.println("子类getThis"); returnthis; } publicstaticvoidmain(String[]args){ /* *从下面a.i与b.i的输出可以看出,某对象的属性只与声明的类型相*关,与对象本身是什么类型无关,这与方法是完全不同的*/Aa=newB(); System.out.println("main方法a.i="+a.i); Bb=(B)a; System.out.println("main方法b.i="+b.i); /* *output: 父类构造方法i=1 子类方法f()i=0 子类getThis 父类中true 子类构造方法i=2 父类getThis 子类中true main方法a.i=1 main方法b.i=2 */} }

[java] view plaincopy

    publicclassA{//这行不能去掉,否则①编译通不过inti=1;A(){System.out.println("父类构造方法i="+this.i);//①this.f();//②System.out.println("父类中"+(this==getThis()));//③print:true}publicvoidf(){System.out.println("父类方法f()i="+this.i);}publicAgetThis(){System.out.println("父类getThis");returnthis;}}classBextendsA{inti=2;B(){System.out.println("子类构造方法i="+this.i);System.out.println("子类中"+(this==super.getThis()));//④}publicvoidf(){System.out.println("子类方法f()i="+this.i);}publicAgetThis(){System.out.println("子类getThis");returnthis;}publicstaticvoidmain(String[]args){/**从下面a.i与b.i的输出可以看出,某对象的属性只与声明的类型相*关,与对象本身是什么类型无关,这与方法是完全不同的*/Aa=newB();System.out.println("main方法a.i="+a.i);Bb=(B)a;System.out.println("main方法b.i="+b.i);/**output:父类构造方法i=1子类方法f()i=0子类getThis父类中true子类构造方法i=2父类getThis子类中truemain方法a.i=1main方法b.i=2*/}}

这里一直有个疑问:上面①②处的this肯定都是同一个对象,且都指向子类对象,还并且与子类中this是同一象,由第③④行代码可以证明这一点。但为什么①处的this好像指向了父类对象,不然为什么①处输出的i是父类中的i呢?这说明属性除了只与定义他的类型有关外,如果在类的内部自身访问时,就会访问当前所在类的属性,与this无关,这进一步说明了属性是不具有多态这一特性的。躲在某一时间想念一段时光的掌纹,

java中的方法能重写,属性能重写吗?

相关文章:

你感兴趣的文章:

标签云: