final 关键字的总结

  • final关键字的总结

  • ——final ,通常指的是“这是无法改变的”。不想做改变可能由于两种理由:设计效率
  • final可能用到的三个情况:数据方法
1、final数据
有时告诉编译器数据恒定不变是很有用的,比如:
  1. 一个永不改变的编译时常量
  2. 一个在运行时被初始化的值,而你不希望它被改变。
  • 对于编译期常量这种情况,编译器可以将该常量值带入任何可能用到它的计算式中,也就是说,可以在编译时执行计算式,这减轻了一些运行时的负担。在Java中,这类常量必须是基本数据类型,并且以关键字final表示。在对这个常量进行定义的时候,必须对其进行赋值。
一个既是static有时final的域之占据一段不能改变的存储空间。并且根据惯例:将用大写表示,并使用下划线分隔各个单词。

final作用于域:
  • 基本类型:数据是无法改变的。
  • 对象类型:对象的引用是无法改变的,而对象的本身是可以改变的。

class Value{

   int i//package access

   public Value(int i) {

      this.i = i;

   }

}

 

public class FinalDate {

 

   private static Random rand = new Random(47);

   private String id;

   public FinalDate(String id) {

      this.id = id;

   }

  

   //Can be compile-time constants

   private final int valueOne = 9;

   private static final int VALUE_TWO = 99;

  

   //Typical public constant:

   public static final int VALUE_THREE = 39;

  

   //Cannot be compile-time constants

   private final int i4 = rand.nextInt(20);

   static final int INT_5 = rand.nextInt(20);

  

   private Value v1 = new Value(11);

   private final Value v2 = new Value(22);

   private static final Value VAL_3 = new Value(33);

  

   //Arrays:

   private final int[] a = {1,2,3,4,5,6};

  

   public String toString()

   {

      return id + ":" + "i4 = " + i4 + ",INT_5 = " + INT_5;

   }

  

   public static void main(String[] args) {

     

      FinalDate fd1 = new FinalDate("fd1");

      //The final field FinalDate.valueOne cannot be assigned

      !fd1.valueOne++;

      fd1.v2.i++; //Object isn't constants

      fd1.v1 = new Value(9); //OK --not final

      for(int i=0; i<fd1.a.length; i++)

      {

         fd1.a[i]++; //Object isn't constants

      }

      The final field FinalDate.v2 cannot be assigned

      fd1.v2 = new Value(0);

      /*

      - The final field FinalDate.VAL_3 cannot be assigned

      - The static field FinalDate.VAL_3 should be accessed in a

       static way

      */

      fd1.VAL_3 = new Value(10);

      //Can't change reference

      fd1.a= new int[3];

      System.out.println(fd1);

      System.out.println("Creating new FinalData!");

      FinalDate fd2 = new FinalDate("fd2");

      System.out.println(fd1);

      System.out.println(fd2);

   }

}

 

∴ -->>将final数值定义为静态和非静态的区别只有当数值在运行时内被初始化时才会显现。


2、空白final:声明final但又未给定初始值的域。
                                                                                 ——因此一个类中的final域就可以做到根据对象而有所不同却又保持其恒定不变的特性。
注意:如果整个程序中无初始化语句,则编译器报错。

3、final参数:这意味着你无法在方法中更改参数引用所指向的对象。
——这一特性主要用来向匿名内部类传递数据。

class Gizmo{

   public void spin(){}

}

 

public class FinalArguments {

 

   void with(final Gizmo g)

   {

      g = new Gizmo();   //Illegal -- g is final

   }

  

   void without(Gizmo g)

   {

      g = new Gizmo();   // OK  --g not final

      g.spin();

   }

  

   void f(final int i)

   {

      //You can only read from a primitiye.

      i++;  // Can't change.

   }

  

   int g(final int i)

   {

      return i+1;

   }

  

   public static void main(String[] args) {

     

      FinalArguments finalArguments = new FinalArguments();

      finalArguments.without(null);

      finalArguments.with(null);

   }

}


4、final方法

使用final方法的原因有两个:

  1. 把方法锁定,以防任何基础类修改它的含义。这是处于设计的考虑:想要确保在继承中使方法行为保持不变,并且不会被覆盖
  2. 效率。在Java早起的实现中,如果将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳过插入程序代码这种正常方式而执行方法调用机制将参数压入栈,跳至方法代码处并执行,然后跳回并清理栈中的参数,处理返回值),并且以方法体中的实际代码的副本来替代方法调用。这将消除方法调用的开销。当然,如果一个方法很大,你的程序代码就会膨胀,因而可能看不到内嵌带来的任何性能提高,因为,所带来的性能提高会因为花费于方法内的时间量而被缩减。

    在最近的Java版本中,虚拟机(特别是hotspot技术)可以探测到这些情况,并优化去掉这些效率反而降低的额外的内嵌调用,因此不再需要使用final方法来优化了。事实上,这种做法正在逐渐地受到劝阻。在使用Java SE5/6时,应该让编译器和JVM去处理效率的问题, 只有在想要明确禁止覆盖时,才将方法设置为final的。

private 和 final :
  1. 如果方法为private,它就不是基类接口的一部分。它仅是一些隐藏于类中的程序代码,只不过是具有相同的名称而已。
  2. 但如果在导出类中以相同的名称生成一个public 、protected或包访问权限方法的话,该方法就不会产生在基类中出现的“仅具有相同名称”的情况。此时你并没有覆盖该方法,仅是生成一个新的方法。

class WithFinals{

   //Indentical 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.f()");

   }

}

 

class OverridingPrivate2 extends OverridingPrivate{

   public final void f()

   {

      System.out.println("OverridingPrivate2.f()");

   }

   public void g()

   {

      System.out.println("OverridingPrivate2.g()");

   }

}

 

public class FinalOverridingIllusion {

 

   public static void main(String[] args) {

     

      OverridingPrivate2 op2 = new OverridingPrivate2();

      op2.f();

      op2.g();

      //You can upcast

      OverridingPrivate op = op2;

      op.f();  //The method f() from the type OverridingPrivate is not visible

      op.g();  //The method f() from the type OverridingPrivate is not visible

      WithFinals wf = op2;

      wf.f();  //The method f() from the type OverridingPrivate is not visible

      wf.g();  //The method f() from the type OverridingPrivate is not visible

   }

}


5、final类:被final修饰的类,无法被继承。
  • final类的域是可以根据个人的医院选择为是或不是final。不论类是否被定义为final,相同的规则都适用于定义为final的域。
  • 由于final类禁止继承,所以final类中所有的方法都隐式指定为final的,因为无法覆盖它们。因此在final类中可以给方法添加final修饰词,但是这不会增加任何意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值