`
songhongchen
  • 浏览: 121391 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

谈使用final关键字

阅读更多
   使用final关键字修饰类、方法和变量的作用大家都知道。不做过多介绍了,google搜索一下很多的。
    在使用final修饰方法的时候,编译器会将被final修饰过的方法插入到调用者代码处,提高运行速度和效率,但被final修饰的方法体不能过大,编译器可能会放弃内联,但究竟多大的方法会放弃,我还没有做测试来计算过。

本文是通过两个疑问来继续阐述的:
1、使用final修饰方法会提高速度和效率吗;
见下面的测试代码,我会执行五次:
public class Test
{
	public static void getJava()
	{
		String str1 = "Java ";
		String str2 = "final ";
		for (int i = 0; i < 10000; i++)
		{
			str1 += str2;
		}
	}
	public static final void getJava_Final()
	{
		String str1 = "Java ";
		String str2 = "final ";
		for (int i = 0; i < 10000; i++)
		{
			str1 += str2;
		}
	}
	public static void main(String[] args)
	{
		long start = System.currentTimeMillis();
		getJava();
		System.out.println("调用不带final修饰的方法执行时间为:" + (System.currentTimeMillis() - start) + "毫秒时间");
		start = System.currentTimeMillis();
		String str1 = "Java ";
		String str2 = "final ";
		for (int i = 0; i < 10000; i++)
		{
			str1 += str2;
		}
		System.out.println("正常的执行时间为:" + (System.currentTimeMillis() - start) + "毫秒时间");
		start = System.currentTimeMillis();
		getJava_Final();
		System.out.println("调用final修饰的方法执行时间为:" + (System.currentTimeMillis() - start) + "毫秒时间");
	}
}

结果为:
第一次:
调用不带final修饰的方法执行时间为:1732毫秒时间
正常的执行时间为:1498毫秒时间
调用final修饰的方法执行时间为:1593毫秒时间
第二次:
调用不带final修饰的方法执行时间为:1217毫秒时间
正常的执行时间为:1031毫秒时间
调用final修饰的方法执行时间为:1124毫秒时间
第三次:
调用不带final修饰的方法执行时间为:1154毫秒时间
正常的执行时间为:1140毫秒时间
调用final修饰的方法执行时间为:1202毫秒时间
第四次:
调用不带final修饰的方法执行时间为:1139毫秒时间
正常的执行时间为:999毫秒时间
调用final修饰的方法执行时间为:1092毫秒时间
第五次:
调用不带final修饰的方法执行时间为:1186毫秒时间
正常的执行时间为:1030毫秒时间
调用final修饰的方法执行时间为:1109毫秒时间

    由以上运行结果不难看出,执行最快的是“正常的执行”即代码直接编写,而使用final修饰的方法,不像有些书上或者文章上所说的那样,速度与效率与“正常的执行”无异,而是位于第二位,最差的是调用不加final修饰的方法。
观点:加了比不加好一点。


1、使用final修饰变量会让变量的值不能被改变吗;
见代码:
public class Final
{
	public static void main(String[] args)
	{
		Color.color[3] = "white";
		for (String color : Color.color)
			System.out.print(color+" ");
	}
}

class Color
{
	public static final String[] color = { "red", "blue", "yellow", "black" };
}

执行结果:
red blue yellow white
看!,黑色变成了白色。
    在使用findbugs插件时,就会提示public static String[] color = { "red", "blue", "yellow", "black" };这行代码不安全,但加上final修饰,这行代码仍然是不安全的,因为final没有做到保证变量的值不会被修改!原因是:final关键字只能保证变量本身不能被赋与新值,而不能保证变量的内部结构不被修改。例如在main方法有如下代码Color.color = new String[]{""};就会报错了。那可能有的同学就会问了,加上final关键字不能保证数组不会被外部修改,那有什么方法能够保证呢?答案就是降低访问级别,把数组设为private。这样的话,就解决了数组在外部被修改的不安全性,但也产生了另一个问题,那就是这个数组要被外部使用的。
解决这个问题见代码:
import java.util.AbstractList;
import java.util.List;

public class Final
{
	public static void main(String[] args)
	{
		for (String color : Color.color)
			System.out.print(color + " ");
		Color.color.set(3, "white");
	}
}

class Color
{
	private static String[] _color = { "red", "blue", "yellow", "black" };
	public static List<String> color = new AbstractList<String>()
	{
		@Override
		public String get(int index)
		{
			return _color[index];
		}
		@Override
		public String set(int index, String value)
		{
			throw new RuntimeException("为了代码安全,不能修改数组");
		}
		@Override
		public int size()
		{
			return _color.length;
		}
	};

}这样就OK了,既保证了代码安全,又能让数组中的元素被访问了。
11
1
分享到:
评论
9 楼 u011922057 2015-01-20  
使用final修饰变量会让变量的值不能被改变吗--楼主给的这一条例子我认为不恰当

因为新建一个新的数组 相当于 new一个对象,加final相当于在堆中给这个数

组分配了一个固定的首地址,这是第一步,第二步,JVM会根据数组的长度在堆中分配相应的内

存,这些内存对应的数组元素是可变的,因为final只修饰该数组的首地址,他对数组内容却没

有限制 
8 楼 一念思量LG 2014-12-16  
路过,
7 楼 lmlyq 2009-04-08  
调用不带final修饰的方法执行时间为:2766毫秒时间
正常的执行时间为:2156毫秒时间
调用final修饰的方法执行时间为:1875毫秒时间

调用不带final修饰的方法执行时间为:2000毫秒时间
正常的执行时间为:2000毫秒时间
调用final修饰的方法执行时间为:1813毫秒时间


我执行最快的是final的也,呵呵~
6 楼 songhongchen 2009-04-08  
星情泪 写道

不太明白,直接给Color设置一个get方法,不设set方法,不就行了吗

覆盖的话就是给调用者更清楚的错误提示.相当于包装了java.lang.UnsupportedOperationException异常.
5 楼 whaosoft 2009-04-08  
呵呵 节省了点时间
4 楼 pf_miles 2009-04-07  
1.final会使编译器以类似inline的方式将源码编译成字节码,运行起来会快一点,不过这个微乎其微,以这点效率抛弃面向对象特性,不值;
2.final作用于对象,是指对象的引用不可变,而不是这个对象本身不可变,也就是说,被final修饰的引用不能再被赋值。
3 楼 星情泪 2009-04-07  
不太明白,直接给Color设置一个get方法,不设set方法,不就行了吗
2 楼 nice_boy 2009-04-07  
简单,明了。
1 楼 flyfan 2009-04-07  
不错,学习了

相关推荐

    Java中final关键字详解

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

    浅谈Java中的final关键字与C#中的const, readonly关键字

    下面小编就为大家带来一篇浅谈Java中的final关键字与C#中的const, readonly关键字。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    深入了解final在java中的应用

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

    一篇文章快速了解Java中的继承与多态

    防止拓展与重写 —final关键字二. 多态6.1 介绍6.2 动态绑定6.3 对象转换和instanceof()运算符6.3.1 对象转换6.3.2instanceof运算符 一. 继承 1.介绍 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中...

    Java入门教程(微学苑)-part1

    4.15 Java final关键字:阻止继承和多态 76 4.16 类与类之间的关系 78 4.17 依赖(uses-a) 78 4.18 聚合(has-a) 78 4.19 继承 79 4.20 Java Object类 79 4.21 equals() 方法 79 4.22 hashCode() 方法 80 4.23 ...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    11.2.4 理解final关键字 296 11.2.5 总结:类的修饰符 297 11.3 方法的修饰符 297 11.3.1 方法的访问控制符 298 11.3.2 public:没有限制的修饰符 299 11.3.3 protected:仅对子类和同包的类可见 300 11.3.4 ...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    11.2.4 理解final关键字 296 11.2.5 总结:类的修饰符 297 11.3 方法的修饰符 297 11.3.1 方法的访问控制符 298 11.3.2 public:没有限制的修饰符 299 11.3.3 protected:仅对子类和同包的类可见 300 11.3.4 ...

    javaSE代码实例

    16.6 volatile关键字的含义与使用 372 16.7 小结 373 第17章 高级线程开发 374 17.1 线程池的使用 374 17.1.1 线程池的基本思想 374 17.1.2 JavaSE 5.0中固定尺寸线程池的基本知识 374 17.1.3 自定义...

    21天学通Java-由浅入深

    60分钟) 217 11.1 异常处理基本介绍 217 11.1.1 try和catch捕获异常 217 11.1.2 try-catch语句使用注意点 218 11.1.3 finally语句的使用 220 11.1.4 再谈异常处理注意点 222 11.2 异常的分类 223 11.2.1 捕获异常 ...

    net学习笔记及其他代码应用

    28.SQLSERVER服务器中,给定表 table1 中有两个字段 ID、LastUpdateDate,ID表示更新的事务号, LastUpdateDate表示更新时的服务器时间,请使用一句SQL语句获得最后更新的事务号 答:Select ID FROM table1 Where ...

    30天搞定Java–day9

    其它关键字:this、super、abstract、interface、static、final、package、import 谈谈你对面向对象中类和对象的理解,并指出二者的关系? 类:抽象的、概念上的内容 对象:实实在在存在的一个个体 对象是由类派生...

    Scala程序设计(第2版)

    3.9 使用try、catch和final子句 72 3.10 名字调用和值调用 75 3.11 惰性赋值 78 3.12 枚举 79 3.13 可插入字符串 81 3.14 Trait:Scala语言的接口和“混入” 83 3.15 本章回顾与下一章提要 85 ...

Global site tag (gtag.js) - Google Analytics