浅析Java中的finalkeyword

  谈到finalkeyword,想必非常多人都不陌生。在使用匿名内部类的时候可能会经经常使用到finalkeyword。

另外。Java中的String类就是一个final类,那么今天我们就来了解final这个keyword的使用方法。以下是本文的文件夹大纲:

  一.finalkeyword的基本使用方法

  二.深入理解finalkeyword

  若有不正之处。请多多谅解并欢迎指正。

  请尊重作者劳动成果,转载请标明原文链接:

  http://www.cnblogs.com/dolphin0520/p/3736238.html

一.finalkeyword的基本使用方法

  在Java中,finalkeyword能够用来修饰类、方法和变量(包含成员变量和局部变量)。

以下就从这三个方面来了解一下finalkeyword的基本使用方法。

  1.修饰类

  当用final修饰一个类时。表明这个类不能被继承。

也就是说。假设一个类你永远不会让他被继承。就能够用final进行修饰。final类中的成员变量能够依据须要设为final,可是要注意final类中的全部成员方法都会被隐式地指定为final方法。

  在使用final修饰类的时候,要注意慎重选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类。

  2.修饰方法

  以下这段话摘自《Java编程思想》第四版第143页:

  “使用final方法的原因有两个。

第一个原因是把方法锁定。以防不论什么继承类改动它的含义。第二个原因是效率。

在早期的Java实现版本号中,会将final方法转为内嵌调用。可是假设方法过于庞大。可能看不到内嵌调用带来的不论什么性能提升。在近期的Java版本号中,不须要使用final方法进行这些优化了。

  因此,假设仅仅有在想明白禁止 该方法在子类中被覆盖的情况下才将方法设置为final的。

  注:类的private方法会隐式地被指定为final方法。

  3.修饰变量

  修饰变量是final用得最多的地方,也是本文接下来要重点阐述的内容。首先了解一下final变量的基本的语法:

  对于一个final变量,假设是基本数据类型的变量。则其数值一旦在初始化之后便不能更改;假设是引用类型的变量,则在对其初始化之后便不能再让其指向还有一个对象。

  举个样例:

  

  上面的一段代码中,对变量i和obj的又一次赋值都报错了。

二.深入理解finalkeyword

  在了解了finalkeyword的基本使用方法之后,这一节我们来看一下finalkeywordeasy混淆的地方。

1.类的final变量和普通变量有什么差别?

  当用final作用于类的成员变量时,成员变量(注意是类的成员变量。局部变量仅仅须要保证在使用之前被初始化赋值就可以)必须在定义时或者构造器中进行初始化赋值,并且final变量一旦被初始化赋值之后,就不能再被赋值了。

  那么final变量和普通变量究竟有何差别呢?以下请看一个样例:

1
2
3
4
5
6
7
8
9
10
11
public
class
Test {
    public
static void
main(String[] args)  {
        String a =
"hello2"
        final
String b = "hello";
        String d =
"hello";
        String c = b +
2
        String e = d +
2;
        System.out.println((a == c));
        System.out.println((a == e));
    }
}

  


  大家能够先想一下这道题的输出结果。为什么第一个比較结果为true,而第二个比較结果为fasle。这里面就是final变量和普通变量的差别了。当final变量是基本数据类型以及String类型时。假设在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接訪问的这个常量,不须要在执行时确定。这种和C语言中的宏替换有点像。因此在上面的一段代码中,因为变量b被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b 替换为它的  值。

而对于变量d的訪问却须要在执行时通过链接来进行。想必当中的差别大家应该明确了。只是要注意。仅仅有在编译期间能确切知道final变量值的情况下,编译器才会进行这种优化,比方以下的这段代码就不会进行优化:

1
2
3
4
5
6
7
8
9
10
11
12
13
public
class
Test {
    public
static void
main(String[] args)  {
        String a =
"hello2"
        final
String b = getHello();
        String c = b +
2
        System.out.println((a == c));
 
    }
     
    public
static String getHello() {
        return
"hello";
    }
}

  这段代码的输出结果为false。

2.被final修饰的引用变量指向的对象内容可变吗?

  在上面提到被final修饰的引用变量一旦初始化赋值之后就不能再指向其它的对象,那么该引用变量指向的对象的内容可变吗?看以下这个样例:

1
2
3
4
5
6
7
8
9
10
11
public
class
Test {
    public
static void
main(String[] args)  {
        final
MyClass myClass = new
MyClass();
        System.out.println(++myClass.i);
 
    }
}
 
class
MyClass {
    public
int i = 0;
}

  这段代码能够顺利编译通过而且有输出结果,输出结果为1。这说明引用变量被final修饰之后。尽管不能再指向其它对象。可是它指向的对象的内容是可变的。

3.final和static

  非常多时候会easy把static和finalkeyword混淆。static作用于成员变量用来表示仅仅保存一份副本,而final的作用是用来保证变量不可变。看以下这个样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public
class
Test {
    public
static void
main(String[] args)  {
        MyClass myClass1 =
new MyClass();
        MyClass myClass2 =
new MyClass();
        System.out.println(myClass1.i);
        System.out.println(myClass1.j);
        System.out.println(myClass2.i);
        System.out.println(myClass2.j);
 
    }
}
 
class
MyClass {
    public
final double
i = Math.random();
    public
static double
j = Math.random();
}

  执行这段代码就会发现。每次打印的两个j值都是一样的。而i的值却是不同的。从这里就能够知道final和static变量的差别了。

4.匿名内部类中使用的外部局部变量为什么仅仅能是final变量?

  这个问题请參见上一篇博文中《Java内部类具体解释》中的解释,在此处不再赘述。

5.关于final參数的问题

  关于网上流传的”当你在方法中不须要改变作为參数的对象变量时。明白使用final进行声明,会防止你无意的改动而影响到调用方法外的变量“这句话,我个人理解这样说是不恰当的。

  由于不管參数是基本数据类型的变量还是引用类型的变量,使用final声明都不会达到上面所说的效果。

  看这个样例就清楚了:

  上面这段代码好像让人认为用final修饰之后。就不能在方法中更改变量i的值了。殊不知,方法changeValue和main方法中的变量i根本就不是一个变量,由于java參数传递採用的是值传递。对于基本类型的变量,相当于直接将变量进行了拷贝。所以即使没有final修饰的情况下,在方法内部改变了变量i的值也不会影响方法外的i。

  再看以下这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public
class
Test {
    public
static void
main(String[] args)  {
        MyClass myClass =
new MyClass();
        StringBuffer buffer =
new StringBuffer("hello");
        myClass.changeValue(buffer);
        System.out.println(buffer.toString());
    }
}
 
class
MyClass {
     
    void
changeValue(final
StringBuffer buffer) {
        buffer.append("world");
    }
}

  执行这段代码就会发现输出结果为 helloworld。

非常显然。用final进行修饰并没有阻止在changeValue中改变buffer指向的对象的内容。

有人说假如把final去掉了。万一在changeValue中让buffer指向了其它对象怎么办。

有这种想法的朋友能够自己动手写代码试一下这种结果是什么,假设把final去掉了。然后在changeValue中让buffer指向了其它对象,也不会影响到main方法中的buffer,原因在于java採用的是值传递,对于引用变量。传递的是引用的值,也就是说让实參和形參同一时候指向了同一个对象。因此让形參又一次指向还有一个对象对实參并没有不论什么影响。

  所以关于网上流传的final參数的说法。我个人不是非常赞同。

Java中的final具体解释以及用途实战的更多相关文章

  1. 浅析Java中的final关键字(转载)

    自http://www.cnblogs.com/dolphin0520/p/3736238.html转载 一.final关键字的基本用法 在Java中,final关键字可以用来修饰类.方法和变量(包括 ...

  2. 浅析Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  3. [转载]浅析Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  4. 转载:浅析Java中的final关键字

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...

  5. java中的final关键字

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...

  6. 浅析Java中的final关键字(转)

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...

  7. 详解Java中的final关键字

    本文原文地址:https://jiang-hao.com/articles/2019/coding-java-final-keyword.html1 final 简介2 final关键字可用于多个场景 ...

  8. 浅析Java中的final关键字--转

    转载自:http://www.importnew.com/18586.html#comment-581628 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关 ...

  9. Java中关键字final用法

    ///首先声明,本文转载自博客园的海子,链接:http://www.cnblogs.com/dolphin0520/p/3736238.html 浅析Java中的final关键字 谈到final关键字 ...

随机推荐

  1. arc和mrc混用

    arc项目中引用非arc代码   加上“-fno-objc-arc” 非arc项目中引用arc代码 加上“-fobjc-arc”

  2. [luoguP4035] [JSOI2008]球形空间产生器(高斯消元)

    传送门 设球心的坐标为未知量 用最后一个点来表示球面到球心的距离,那么它和前n个式子相等 移项乱搞 最后高斯消元 #include <cmath> #include <cstdio& ...

  3. hdu4336 Card Collector(概率DP,状态压缩)

    In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, fo ...

  4. 2017 ACM/ICPC Asia Regional Xian Online 记录

    题目链接  Xian

  5. Neo4j 第六篇:Cypher语法

    Cypher是图形数据库查询语言事实上的标准. 一,Cypher类型系统 Cypher支持的类型系统分为三类:属性类型,复合类型和结构类型. 1,属性类型 属性类型:Integer.Float.Str ...

  6. 2017-10-29-morning-清北模拟赛

    T1 遭遇 #include <algorithm> #include <cstdio> #include <cmath> inline void read(int ...

  7. Linux内核配置选项

    http://blog.csdn.net/wdsfup/article/details/52302142 http://www.manew.com/blog-166674-12962.html Gen ...

  8. PHP用CURL发送Content-type为application/json的HTTP/HTTPS请求

    <?php $headers = array( "Content-type: application/json;charset='utf-8'", "Accept: ...

  9. Spring boot 整合spring Data JPA+Spring Security+Thymeleaf框架(上)

    近期上班太忙所以耽搁了给大家分享实战springboot 框架的使用. 以下是spring boot 整合多个框架的使用. 首先是准备工作要做好. 第一  导入框架所需的包,我们用的事maven 进行 ...

  10. ubuntu compile php from source code

    10down vote Assuming that you already have the OpenSSL libraries and header files (on rpm systems th ...