深入Java Final

JAVA关键字final用于修饰数据、方法或类,通常意味着“无法改变的”,既数据不能改变,方法不能覆盖,类不能继承。一般采用final有两种原因:设计和效率。而随着JAVA版本的更新,一些效率上的问题可以交由编译器和JVM处理。因此,采用final来解决效率问题就显得不是那么重要了。

Final修饰符大多运用于基本数据类型(primitive)域或者不可变(immutable)类的域(如果类中的所有方法方法都不会改变其对象,这种类就是不可变类。String就是一个不可变类)。

【final数据】

Final关键字用修饰数据主要有两种情况:

1. 编译期常量

2. 运行时初始化的值

对于编译期常量,指的是一个既是final又是static的域(依照惯例,编译期常量全部用大写字母命名,并且用下划线分隔各个单词),它只占据一段不能改变的存储空间。编译器可以将编译期常量代入到任何可能用到它的计算式中,也就是说,可以在编译时执行计算式,这相对减轻了运行时负担。编译期常量在定义时必须对它赋值(不一定是基本类型)。

运行时初始化的值,对于基本类型,final使得其值不可改变;而对于对象引用,final使得引用不可改变,即无法将其改为指向另一个对象,然而,对象本身却可以修改(适用于数组,数组也是对象)。

代码如下:

public class javaFinalData{

private static final String TESTD = "test";
    public static final String TESTE = "test";
    public static final String[] TESTF = {"1","2"}; //非基本类型
    private static final String[] TESTG = new String[2];

public static void main(String args[]){
        final int testA = 1;
        final String testB = "test";
        final int[] testC = {1,1,2,};
        System.out.println(testC[1]);
        testC[1] = 123;
        System.out.println(testC[1]);
    }
}

【未赋值的final域】

JAVA允许生成未赋值的final域,但是必须在域的定义处或者每个构造器中对final域进行赋值(有多少个构造器就必须赋值几次),确保在使用前被初始化。采用这种方式,可以使得final运用得更加灵活,在同一个类中,根据不同的对象赋予不同的值,却又保持不可改变的特性。


代码如下:

public class javaBlankFinal{
    private final int blank;

public javaBlankFinal(){
        blank = 2011;
    }

public javaBlankFinal(int temp){
        blank = 2012;
    }

public javaBlankFinal(String temp){
        blank = 2014;
    }

public static void main(String args[]){
        new javaBlankFinal();
    }
}

【final方法】

使用final方法有两方面原因:一是将方法锁定,防止方法被覆盖,确保在继承中方法行为保持不变;二是将方法调用转为内联调用(inlining),以减少方法调用的开销。但是,在最近的版本中,JVM可以自行进行优化,因此无需使用final方法来处理效率问题。

关于final方法,还有一点需要注意,类中所有的private方法都隐式地指定为final方法(也可以为其加上final修饰,但没有意义)。当你试图覆盖一个private方法,编译器并没有报错,但是,实际上你并没有覆盖该方法,只是生成了一个新方法。因为private方法是无法被外部类所访问的,当然就无法覆盖到它了。

使用@Override注解可以防止上述问题。如程序所示:

代码如下:

class finalFunction{
    private void finalFunctionA(){
        System.out.println("finalFunctionA");
    }

private final void finalFunctionB(){
        System.out.println("finalFunctionB");
    }

final void finalFunctionC(){
        System.out.println("finalFunctionC");
    }

void functionD(){}
}

class overrideFinalFunction extends finalFunction{
    //@Override   添加@Override注解可以识别是否是override
    public void finalFunctionA(){              
        System.out.println("override finalFunctionA");
    }

public final void finalFunctionB(){
        System.out.println("override finalFunctionB");
    }

//final void finalFunctionC(){}   //Cannot override the final method from finalFunction

@Override  
    void functionD(){} //真正的override方法
}

public class javaFinalFunction extends finalFunction{
    public static void main(String args[]){
        finalFunction ff = new finalFunction();
        //ff.finalFunctionA();  //无法调用private方法
        //ff.finalFunctionB();

overrideFinalFunction off = new overrideFinalFunction();
        off.finalFunctionA();   //public方法
        off.finalFunctionB();
    }
}

【final类】

使用final类一般是出于设计原因,不允许该类被继承。这样可以保证类的行为不会改变,或许还能避免一些安全危机。Final类中所有的方法都隐式指定为final方法,因此无法被覆盖(因为final类禁止继承,也就无法覆盖其类中的方法)。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止覆盖length()等方法。

对于final域来说,即使将一个类声明为final,类中的域不会自动成为final域。


代码如下:

final class finalClass{
    int testA = 2011;
}
//class extendFinalClassextends finalClass{}  //can not extendthe final class finalClass

public class javaFinalClass{
    public static void main(String args[]){
       finalClass fc = new finalClass();
       System.out.println(fc.testA);
       fc.testA = 2012;
       System.out.println(fc.testA);
    }
}

(0)

相关推荐

  • java中final与finally的使用介绍

    final可以修饰类 ,成员变量,局部变量和方法. 1.final修饰成员变量 1.final成员变量的初始化 对于final修饰的变量,系统不会默认初始化为0 fina变量初始化方式: 在定义的时候初始化 final变量可以在初始化块中初始化,不可以在静态初始化块中初始化. 静态final变量可以在静态初始化块中初始化,不可以在初始化块中初始化. fina变量还可以在构造函数中初始化,但是静态final变量不可以. 2.final修饰方法 当final用来修饰方法时,表示这个方法不可以被子类覆

  • java面向对象基础_final详细介绍

    final: 继承的弊端:打破了代码的封装性,final的出现正好弥补了这一弊端 final关键字: 1-final是一个修饰符,可以修饰类,方法,变量; 2-final修饰的类不能被继承 3-final修饰的方法不可以被覆盖 4-final修饰的变量是一个常数,只能被赋值一次并且要在定义时就将其赋予某值 规则: 被定义final的常量要用大写字母表示,各单词之间用下划线_来隔开. 实例一: class Father01{ final String FATHER01_NAME = "张三&quo

  • java中final修饰符实例分析

    final修饰符: final修饰成员变量必须有程序员显示指定初始值. 类的Field:必须在静态初始化块中或声明该Field时指定初始值. 实例Field:必须在非静态初始块中,声明Field或者构造器中指定初始值. final局部变量:必须由程序员显示初始化. final修饰的基本变量和引用类型变量的区别? final修饰的基本变量:不能对基本变量重新赋值. final修饰的引用变量:只保证这个引用类型所引用的地址不会变,即 一直引用同一个对象,但这个对象完全可以发生改变. 复制代码 代码如

  • Java final 修饰符知识点总结(必看篇)

    final从字面上理解含义为"最后的,最终的".在Java中也同样表示出此种含义. final可以用来修饰变量(包括类属性.对象属性.局部变量和形参).方法(包括类方法和对象方法)和类. 1. final修饰类: final修饰类即表示此类已经是"最后的.最终的"含义.因此,用final修饰的类不能被继承,即不能拥有自己的子类. 如果视图对一个已经用final修饰的类进行继承,在编译期间或发生错误. 2. final修饰方法: final修饰的方法表示此方法已经是&

  • java关键字final使用方法详解

    它所表示的是"这部分是无法修改的".不想被改变的原因有两个:效率.设计.使用到final的有三种情况:数据.方法.类. 一. final数据 有时候数据的恒定不变是很有用的,它能够减轻系统运行时的负担.对于这些恒定不变的数据我可以叫做"常量"."常量"主要应用与以下两个地方:1.编译期常量,永远不可改变.2.运行期初始化时,我们希望它不会被改变.对于编译期常量,它在类加载的过程就已经完成了初始化,所以当类加载完成后是不可更改的,编译期可以将它代入

  • Java修饰符 abstract,static,final 的区别详解

    static 表示静态,它可以修饰属性,方法和代码块. 1.static修饰属性(类变量),那么这个属性就可以用类名.属性名来访问,也就是使这个属性成为本类的类变量,为本类对象所共有.这个属性就是全类公有.(共有的类变量与对象无关,只和类有关). 类加载的过程,类本身也是保存在文件中(字节码文件保存着类的信息)的,java会通过I/O流把类的文件(字节码文件)读入JVM(java虚拟机),这个过程成为类的加载.JVM(java虚拟机)会通过类路径(CLASSPATH)来找字节码文件. 类变量,会

  • java中final关键字使用示例详解

    final经常和static一起使用来声明常量,你也会看到final是如何改善应用性能的.final关键字的含义?final在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译错误.什么是final变量?凡是对成员变量或者本地变量(在方法中的或者代码块中的变量称为本地变量)声明为final的都叫作final变量.final变量经常和static关键字一起使用,

  • java中final修饰符的使用方法

    本文为大家分享了java中final修饰符的使用,供大家参考,具体内容如下 1.final修饰符的用法: final可以修饰变量,被final修饰的变量被赋初始值之后,不能对它重新赋值. final可以修饰方法,被final修饰的方法不能被重写. final可以修饰类,被final修饰的类不能够被继承. 上面的这些"语法口诀"对真正掌握final修饰符的用法依然是不够的. 2.final修饰的变量:被final修饰的实例变量必须显示指定初始值,而且只能在如下三个位置指定初始值: 定义f

  • 完全解析Java编程中finally语句的执行原理

    可不能小看这个简单的 finally,看似简单的问题背后,却隐藏了无数的玄机.接下来我就带您一步一步的揭开这个 finally 的神秘面纱. 问题分析 首先来问大家一个问题:finally 语句块一定会执行吗? 很多人都认为 finally 语句块是肯定要执行的,其中也包括一些很有经验的 Java 程序员.可惜并不像大多人所认为的那样,对于这个问题,答案当然是否定的,我们先来看下面这个例子. 清单 1. public class Test { public static void main(St

  • Java中final变量使用总结

    final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值. 通常final定义的变量为常量.如: 复制代码 代码如下: final double PI = 3.14; 当在程序中使用PI这个常量时,它的值就是3.14,如在程序中再次对定义为final的常量赋值,编译器将不能接受: final关键字定义的变量必须在声明时对其进行赋值操作.final除了可以修饰基本数据类型的常量,还可以修饰对象引用.由于数组也可以被用作一个对象引用,所以final可以修饰数组.一旦一个对象引用被修

随机推荐