final数据只能够在定义时初始化,或者是在声明blank final后在构造函数中初始化。对于基本类型,final域值不可变,对于引用类型,
final的引用指向不可变,可是其引用所指向的对象的属性实际上是可变的。
final 数据能够被继承的,而且能够被子类同名属性覆盖,参看示例:安全
public class SuperAttribute { public final String str = "父类的final属性"; public final String strNotHide = "父类的final属性 没有被隐藏的 能够被子类继承的"; } public class SubAttribute extends SuperAttribute { public final String str = "子类的final属性"; @Test public void test() throws Exception { //父类引用指向子类对象 属性是不存在多态性的 SuperAttribute supera = new SubAttribute(); System.out.println(supera.str);//输出 父类的final属性 SubAttribute sub= new SubAttribute(); System.out.println(sub.str);//输出 子类的final属性 System.out.println(sub.strNotHide);//父类的final属性 没有被隐藏的 而且这个final属性是能够继承的 } }
Java容许在参数列表中以声明的方式将参数指明为final。这样就没法在方法中更改参数引用所指向的对象。这一特性主要用来向匿名内部类传递数据。ide
如今使用final方法的缘由只有一个:把方法锁定,以防止任何继承类修改他的含义,想要确保继承中使方法行为保持不变,
而且不会覆盖。记住,final方法的含义只有一个:方法不可被子类改变(重写override和覆盖隐藏hiding)函数
对于实例方法final的含义为:在子类中不能够重写这个方法
对于静态方法final的含义为: 在子类中不能够隐藏(覆盖)这个方法
示例代码以下:this
public class SuperFinalMethod { public final void finalMethod(){ System.out.println("父类的final方法"); } public static void staticFinalMethod(){ System.out.println("父类的static final方法"); } public static final void staticFinalMethodNotHide(){ System.out.println("父类的static final方法 没有覆盖"); } public static void main(String[] args) { } } public class SubFinalMethod extends SuperFinalMethod{ /** * Cannot override the final method from SuperFinalMethod * 实例final方法是不能够被override(重写)的,方法签名一致就不能够 public final void finalMethod(){ System.out.println("父类的final方法"); } */ /** * 实例final方法虽然不能够被重写,可是在子类中能够重载这个final方法 */ public final void finalMethod(int i){ finalMethod();//从父类中继承了 System.out.println("父类的final方法"); } //隐藏(覆盖)父类的静态方法 public static void staticFinalMethod(){ System.out.println("子类的static final方法"); } /** * <b>不能够经过编译</b> * * 编译器给出的提示信息: * SubFinalMethod 中的 staticFinalMethodNotHide() 没法覆盖 SuperFinalMethod 中的 * staticFinalMethodNotHide();被覆盖的方法为 static final * *Eclipse给出的提示信息是错误的:Cannot override the final method from SuperFinalMethod *staticFinalMethodNotHide()方法是静态的,不能够重写(),只能覆盖,可是又因为staticFinalMethodNotHide()方法是 *final的,因此也没法覆盖。 * *因此final对于实例方法和静态方法的含义是不一样的 *对于静态方法final的含义是不可覆盖(不可隐藏 can't hiding) *对于实例方法final的含义是不可重写override *总之final方法含义就是子类继承的这个方法不可变(不可重写,不可隐藏覆盖) public static final void staticFinalMethodNotHide(){ System.out.println("父类的static final 方法是没法覆盖的"); } */ }
类中全部的private方法都隐式的指定为final的。因为没法取用private方法,因此也就没法覆盖它。(private方法在继承类中
是没法使用的,天然也就没有覆盖之说了)
可是下面的情形可能会引发一些疑惑。设计
class WithFinals { // Identical to "private" alone: private final void f() { System.out.println("WithFinals.f()"); } // Also automatically "final": private void g() { System.out.println("WithFinals.g()"); } } class OverridingPrivate extends WithFinals { private final void f() { System.out.println("OverridingPrivate.f()"); } private void g() { System.out.println("OverridingPrivate.g()"); } } class OverridingPrivate2 extends OverridingPrivate { public final void f() { System.out.println("OverridingPrivate2.f()"); } public void g() { System.out.println("OverridingPrivate2.g()"); } } public class FinalOverridingIllusion { private static Test monitor = new Test(); public static void main(String[] args) { OverridingPrivate2 op2 = new OverridingPrivate2(); op2.f(); op2.g(); // You can upcast: OverridingPrivate op = op2; // But you can't call the methods: //! op.f(); //! op.g(); // Same here: WithFinals wf = op2; //! wf.f(); //! wf.g(); monitor.expect(new String[] { "OverridingPrivate2.f()", "OverridingPrivate2.g()" }); } } ///:~
"覆盖"只有在某方法是基类的接口的一部分时才会出现。即,必须能将一个对象向上转型为它的基本类型并调用相同的方法。
若是某个方法为private,它就不是基类接口的一部分。若是在导出类中以相同的名称生成一个public,protected,defualt
方法,则只是生成了一个新的方法。与是否覆盖并无关系。
另外,对于覆盖,必须方法签名一致才是覆盖,若是方法签名不一致,好比方法参数不一样,也存在覆盖。以下所示:code
public class FinalObj { void defaultFinalMethod(String str) { System.out.println(" defaultFinalMethod " + str); } public final void protectedfinalMethod(String str) { System.out.println(" FinalObj protected final " + str); } public void protectedMethod(String str) { System.out.println(" FinalObj protected " + str); } } public class FinalObjSub extends FinalObj { @Override public void protectedMethod(String str) { System.out.println(" FinalObjSub protected " + str); } /** @Override 没法经过编译,由于父类中不存在这个方法,也没有覆盖之说 public void protectedMethod(int str) { System.out.println(" FinalObj protected " + str); } */ }
当将某个类总体定义为final时,就代表你不打算继承该类,并且也不容许别人这么作。换句话说,你对该类的设计用不须要
作出任何变更,或者是出于安全考虑,你不但愿它有子类。对象
静态方法是能够继承的,可是在子类中即便能够定义一个与父类方法签名相同的方法会覆盖掉父类的方法,可是这并非重写
重写应该体如今多态性上有所体现,可是覆盖父类静态方法并不会体现多态性。看看下面的实例代码:继承
public class SuperStaticObj { public final void finalMethod(){ System.out.println(" super finalMethod"); } public void method() {//普通实例方法 体现多态性,能够由子类继承并能够重写override System.out.println("fatherMethod"); } //静态方法,不体现多态性,能够由子类继承,可是不能够重写(orverride),只能够覆盖 public static void staticMethod() { System.out.println("fatherStaticMethod"); } public static void staticMethodNotHide() { System.out.println("fatherStaticMethodNotHide"); } } public class SubStaticObj extends SuperStaticObj { @Override public void method() { System.out.println("SubMethod"); } /** *父类中也存在相同的方法签名的staticMethod()方法,在子类中定义一个与父类相同方法签名的 *静态方法这种方式并非覆写,而只是隐藏(覆盖)了父类的静态方法,若是是覆写的话,那么在父类引用指向 *子类对象时,对象会表现出多态性 *请参考test4Static()方法 */ public static void staticMethod() { System.out.println("SubStaticMethod"); } /** *能够直接在子类中调用父类的静态方法,说明父类的静态方法是继承了的 */ public static void staticMethodFromSuperType() { staticMethodNotHide(); } @Test public void test4Static() throws Exception { //父类引用指向子类对象 SuperStaticObj sso = new SubStaticObj(); sso.method();//输出SubMethod 调用的运行时子类的方法 sso.staticMethod();/** 输出 fatherStaticMethod 虽然父类引用指向的是子类对象,可是仍然调用的是父类的方法 **/ } /** * 在子类中直接调用被隐藏的父类的static方法,会调用这个类中的使父类方法隐藏的那个新方法 */ @Test public void test4StaticHide() throws Exception { staticMethod();//SubStaticMethod } }
属性存在继承性,可是却不表现多态性,也就是说属性能够继承不可重写,能够覆盖
多态仅针对实例方法,与实例的属性无关。重写只对方法有效,对属性无效!示例代码:接口
public class SuperAttribute { public int i = 0; public int j = 0; public void printI(){ System.out.println(" 父类 i = " + i +" ,j = " +j); } } public class SubAttribute extends SuperAttribute { //覆盖了父类的i属性i = 0 public int i = 1; public void printI(){ System.out.println(" 子类 i = " + i +" ,j = " +j); } @Test public void test4AttributeCover() throws Exception { //对于属性i 和 j存在继承 super.printI();//i = 0 ,j = 0 printI();//i = 1 ,j = 0 //多态性的验证 父类引用指向子类对象 SuperAttribute sa = new SubAttribute(); sa.printI();//子类 i = 1 ,j = 0 方法具备多态性 System.out.println("i = " + sa.i);//i=0属性不具有多态性,所以也没有重写之说,只是覆盖了父类的同名属性 } }
假设子类从超类中继承了一个方法,在这个方法中须要访问一个属性,即便这个属性在子类中从新被覆盖,那子类对象调用这个父类方法
时仍然访问的是父类的属性。除非在子类中重写父类方法,这样才会访问子类的属性。示例以下:ip
public class SuperAttribute { public int i = 0; public int j = 0; public void printI(){ System.out.println(" 父类 i = " + this.i +" ,j = " +this.j); } public void printJ(){ System.out.println(" 父类 i = " + this.i +" ,j = " +this.j); } } public class SubAttribute extends SuperAttribute { //覆盖了父类的i属性i = 0 public int i = 1; public void printJ(){ System.out.println(" 子类 i = " + this.i +" ,j = " +this.j); } @Test public void test4AttributeCover() throws Exception { //父类引用指向子类对象 SuperAttribute sa = new SubAttribute(); sa.printI();// 父类 i = 0 ,j = 0 访问的是父类的属性 sa.printJ();//子类 i = 1 ,j = 0 override printJ()以后访问的是子类的属性 //子类引用指向子类对象 SubAttribute sub = new SubAttribute(); sub.printI();// 父类 i = 0 ,j = 0 访问的是父类的属性 sub.printJ();//子类 i = 1 ,j = 0 override printJ()以后访问的是子类的属性 } }
author by zhaob time : 2014-09-13 14:18