[Java]"final"关键字的用法和知识点总结(下半部分)

 



  • final参数

Java允许你在参数列表以声明的方式将参数指明为final. 这意味着你无法在方法中更改参数引用所指向的对象.  

 看例子:

  1. //: FinalArguments.java

  2. class Gizmo {
  3.     public void spin() {}
  4. }

  5. public class FinalArguments {
  6.     void with (final Gizmo g) {
  7.         //! g = new Gizmo();  //错误:g不能被更改
  8.     }
  9.     
  10.     void without(Gizmo g) {
  11.         g = new Gizmo();     //没问题
  12.         g.spin();
  13.     }
  14.     
  15.     //void f(final int i) {i++;} //错误:i不能更改
  16.     //final是只读的
  17.     int g(final int i) {return i + 1;}
  18.     
  19.     public static void main(String[] args) {
  20.         FinalArguments bf = new FinalArguments();
  21.         bf.without(null);
  22.         bf.with(null);
  23.     }
  24. }

   方法f()和g()展示了当原始类型的参数被指明为final时所出现的结果:你可以读参数,却无法修改参数. 这一特性看起来仅有微不足道的用处,而且你可能还用不到!呵呵!

来看下一种使用final的情况:


  • final方法
    使用final方法的原因有二:

    1. 将方法锁定,以防任何继承类修改它的意义,这是出于设计的考虑: 你想要确保在继承中方法行为保持不变,并且不会被重载.

        2. 效率. 如果你将一个方法指明为final,就是同意编译器将对该方法的所有调用都转为内嵌(inline)调用. 当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳过插入程序代码的正常方法而执行方法调用机制(将参数压入栈,跳至方法代码处并执行,然后跳回并清除栈中的参数,并处理返回值.), 并且以方法体中的实际代码的副本来代替方法调用.这将消除方法调用的开销. 当然,如果一个方法很大,你的程序代码就会膨胀,你可能看不到内嵌带来的任何性能提高,因此,你所取得的性能提高会因为花费于方法内的时间总量而被缩减. 这意味着Java编译器能够观察到这些情况并明智地抉择是否对final方法执行内嵌动作. 然而,最好是让编译器和JVM仅在你明确表示要阻止重载时,在处理效率事项,并将方法指明为final.


   final和private

        类中所有的private方法都被隐含是final的. 由于你无法取用private方法,所以你无法重载之.你可以对private方法增加final修饰符,但这并不能给该方法增加任何额外的意义

        这个问题会造成混淆. 因为如果你试图重载一个private方法(隐含是final的),看起来是奏效的,而且编译器不会给出错误信息.


        比如:

  1. //: FinalOverridingIllusion.java

  2. class WithFinals {
  3.     private final void f() {
  4.         System.out.println("WithFinals.f()");
  5.     }
  6.     private void g() {
  7.         System.out.println("WithFinals.g()");
  8.     }
  9. }

  10. class OverridingPrivate extends WithFinals {
  11.     private final void f() {
  12.         System.out.println("OverridingPrivate.f()");
  13.     }
  14.     private void g() {
  15.         System.out.println("OverridingPrivate.g()");
  16.     }
  17. }

  18. class OverridingPrivate2 extends OverridingPrivate {
  19.     public final void f() {
  20.         System.out.println("OverridingPrivate2.f()");
  21.     }
  22.     public void g() {
  23.         System.out.println("OverridingPrivate2.g()");
  24.     }
  25. }

  26. public class FinalOverridingIllusion {
  27.     public static void main(String[] args) {
  28.         OverridingPrivate2 op2 = new OverridingPrivate2();
  29.         op2.f();
  30.         op2.g();
  31.         //向上转型一下
  32.         OverridingPrivate op = op2;  //基类引用指向了导出类对
  33.                                             //象,实现向上转型
  34.         //但是你不能调用op的方法
  35.         //! op.f();
  36.         //! op.g();
  37.         WithFinals wf = op2;    //向上转型至WithFinals类型,那
  38.                                //么对象wf就只看到了op2的WithFinals部分
  39.         //! wf.f();
  40.         //! wf.g();
  41.     }
  42. }
    "重载"只有在某方法是基类的接口的一部分时才会出现.即,你必须能将一个对象向上转型为它的基本类型并调用相同的方法.如果某方法为private,他就不是基类的接口的一部分. 它仅是一些隐藏于类中的程序代码,不过具有相同的名称而已.但你 如果在导出类以相同的名称生成一个public,protected或包访问权限方法的话,该方法就不会产生在基类中出现的"仅具有相同名称"的情况. 此时你并没有重载,你仅是生成了一个新的方法.由于private方法无法触及又不能有效隐藏,所以仅仅是因为考虑到定义它的类的程序代码组织,它们才有存在的意义,除此之外,其他任何事物都不需要将它纳入考虑的范畴.
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

  • final 类

   当你将某各类的整体定义为final时(通过将关键字至于它的定义之前),你就声明了你打算继承该类,而且不允许别人这么做. 换句话说,出于某种考虑,你对该类的设计用不需要做任何变动,或者出于安全的考虑,你不希望它有子类.

      例子:

  1. //! Jurassic.java

  2. class SmallBrain {}

  3. final class Dinosaur {
  4.     int i = 7;
  5.     int j = 1;
  6.     SmallBrain x = new SmallBrain();
  7.     void f() {}
  8. }

  9. //!class Further extends Dinosaur {}
  10. //错误:Dinosaur是final的,所以不能继承,但是其类成员可以改变

  11. public class Jurassic {
  12.     public static void main(String[] args) {
  13.         Dinosaur n = new Dinosaur();
  14.         n.f();
  15.         n.i = 40;
  16.         n.j++;
  17.     }
  18. }
  请注意,根据你的选择,final类的数据成员可以是final,同样可以不是. 不论类是否被定义为final,相同的规则都适用于final的数据成员. 然而,由于final类禁止继承,所以final类中所有的方法都被隐含是final的,因为他们是不会被重载的. 在final类中你可以给方法添加final修饰符,但不会添加任何意义.

--------------------未完待续---------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值