码迷,mamicode.com
首页 > 其他好文 > 详细

final关键字

时间:2018-01-14 15:15:58      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:out   type   print   stat   nbsp   ring   rgs   因此   功能   

    final是Java中的一个修饰符,可以用来修饰类,变量,方法。而对于final的理解,也主要围绕这三者来进行。

一、final修饰类

    被final修饰的类我们称为不可变类,例如Java中的String类就是不可变类,他表示该类不能被继承,并且该类

中的方法会默认为final类型,但被final修饰的类中的成员属性并不会默认为final,我们在变成中可根据需求,确定属性

是否为final的。将类设计为final是出于该类不可被继承和一些安全性的考虑。否则就不要将类设计为final了。

二、final修饰方法

    使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在

早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。

在最近的Java版本中,不需要使用final方法进行这些优化了

三、final修饰变量

    若变量为基本数据类型,则该变量在修改之后便不能被更改了,若变量为引用数据类型,则引用不能被更改,也就是该

变量不能再指向其它对象

  • 那final变量与普通变量有什么区别呢?

//网上流传很广的一个例子,但解释的都不怎么样
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
false

这个例子可以很完美体现出二者之间的区别。final修饰基本数据类型或者String类型,要么在定义处进行初始化赋值,要么在

构造器中进行初始化赋值,否则编译报错,赋值之后这个值便不能再被改变,因此Java的编译器很人性化的做了这样一个功能,

就是编译时优化,凡是被final修饰的变量都会进行编译期优化,因为他们的值在编译期已经确定了,因此String c = b + 2直接被

优化为"hello2",而且这个hello2是在字符串常量池中创建的,然而String a = "hello2",已经在字符串常量池中创建了一个hello2,

因此c就不会再创建了,而是直接指向了a所指向的那个hello2,因此a == c为true。而a == e为什么为false是因为当进行

String e = d + 2操作时相当于进行的是new String("hello2"),此时的e指向的是堆中的一个hello2对象,而a指向的是常量池中的,

因此为false。

换应该注意,只有在编译期确切知道变量值才会进行优化,否则则不会进行优化。

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
  • 被final修饰的引用变量所指向的对象的内容是可变的

  • final与static修饰变量的区别?

public class Test {
    public static void main(String[] args)  {
        MyClass myClass1 = new MyClass();
        MyClass myClass2 = new MyClass();
        System.out.println("final i:" + myClass1.i);
        System.out.println("static j:" + myClass1.j);
        System.out.println("final i:" + myClass2.i);
        System.out.println("static j:" + myClass2.j);
 
    }
}
 
class MyClass {
    public final double i = Math.random();
    public static double j = Math.random();
}

结果:

final i:0.19008381769339489
static j:0.04553435249234561
final i:0.24184639133515862
static j:0.04553435249234561

观察发现,尽管调用了两次j,但是值是一样的,所以可知,final修饰变量强调的是该变量不可再被修改,而static修饰变量强调的是

该变量是全局的,静态的,整个类中只能存在一份静态的j,所有该类的实例对象对它的调用都调用的是同一份数据。

  • final也可以修饰方法中的参数

    同理上面也讲过了,当为值传递时,在该方法内这个参数不能再被修改,当为引用传递时,引用的指向不能再被改变,但对象内容还是可以改变的

三、final与voiatile

单独开一篇吧。。。

final关键字

标签:out   type   print   stat   nbsp   ring   rgs   因此   功能   

原文地址:http://blog.51cto.com/12222886/2060751

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!