`
songhongchen
  • 浏览: 122742 次
  • 性别: 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关键字

    在方法参数列表中使用`final`关键字,防止方法内部改变参数引用: ```java public void process(final Object obj) { obj = new Object(); // 不合法 obj.someMutableProperty = "New Value"; // 合法,仅修改对象...

    浅谈Java之终止继承:Final类和Fianl方法

    Java之终止继承是Java语言中的一个重要概念,它通过使用final关键字来控制类和方法的继承。今天,我们将详细介绍Final类和Final方法,並討論他们在Java程序设计中的应用和限制。 一、Final类 Final类是指使用final...

    浅谈Java中static关键字的作用

    static 关键字也可以与 final 结合使用。对于变量,若使用 static final 修饰,表示一旦赋值不能修改,并且通过类名可以访问。对于方法,若使用 static final 修饰,表示该方法不可被覆盖,并且可以通过类名直接访问...

    浅谈Java中方法的参数传值.zip

    在Java中,可以使用final关键字修饰方法参数,确保该参数在方法内部不可修改。这对于防止意外修改参数值和提高代码可读性非常有用: ```java public void useFinalParam(final int num) { num = 10; // 编译错误,...

    浅谈Java程序的性能优化

    1. **避免频繁使用new关键字创建对象**:每次使用new创建对象时,会调用构造函数链,消耗一定资源。如果对象实现了Cloneable接口,可考虑使用clone()方法,它不会调用构造函数,从而节省开销。对于数组,也可以通过...

    java顶岗实习周记(15页)详细心得参考

    在第二周实习中,作者主要学习了java的基础语法,包括类之间的关系、基本数据类型、逻辑语句和循环语句、修饰符、 Static关键字、Final关键字、This关键字、string和stringBuffer等。这些知识点都是java开发者的基础...

    学习Java程序入门-面向对象之封装,继承,多态(下).docx

    - **final关键字**: - **定义**:`final`关键字可以用来修饰类、方法和变量。 - **修饰类**:若一个类被声明为`final`,则该类不能被继承。 - **修饰方法**:若一个方法被声明为`final`,则该方法不能被子类覆盖...

    深入浅出谈java修饰符共6页.pdf.zip

    Java 8引入了默认方法(用`default`关键字)和静态方法(用`static`关键字),增强了接口的功能。 在实际编程中,合理使用这些修饰符可以帮助我们创建更安全、高效和可维护的代码。例如,通过使用`private`来隐藏...

    谈面试时从写一个单例开始究竟能问多深及终极解决方案.docx

    - 类加载:在使用`new`关键字之前,类必须已经被加载、链接和初始化。 - 构造函数调用:`new`操作符会自动调用构造函数来初始化新创建的对象。 #### 终极解决方案 为了提高单例模式的线程安全性和性能,可以采用*...

    java 单例模式(饿汉模式与懒汉模式)

    在饿汉式单例模式中,我们可以使用final关键字来强化和突出“同一对象”的概念,即只有这么一个对象,而且它是不可以被修改的。如果不使用final修饰Single SINGLE,那么就会有这么一种情况:业务很复杂,在不经意间...

    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 ...

    浅谈java 面对对象(抽象 继承 接口 多态)

    **final关键字**用于标记不可变的类、变量和方法。final类不能被继承,final变量一旦初始化后就不能改变,final方法不能被子类重写。在定义常量时,通常使用final并全大写。 **final和private的区别**在于,final...

    浅谈java中的声明常量为什么要用static修饰

    在Java编程语言中,声明常量通常会使用`static`关键字进行修饰,这是为了实现特定的目的和优化。本文将深入探讨为什么在Java中声明常量时需要使用`static`修饰符,以及它带来的益处。 首先,理解`static`关键字的...

    浅谈java的接口和C++虚类的相同和不同之处

    7. final关键字: - 在Java中,接口的所有方法默认都是final的,这意味着子类不能覆盖接口中的方法,而在C++中,抽象类的虚方法可以被覆盖。 8. 实现方式: - C++的虚类通过使用`virtual`关键字指定虚函数,而...

    Java笔记Core java

    类可以通过访问修饰符(public、private、protected、默认)来控制其可见性,也可以通过final关键字使其不可被继承。Java支持单继承,但通过接口可以实现多重继承的效果。构造器是类的特殊方法,用于初始化新创建的...

    浅谈为什么Java里面String类是不可变的

    在 Java 中,final 关键字就是用来辅助创建不可变对象的。 String 类型的不可变性 String 类型的底层是由 final 修饰的 char 数组存储。String 能被设计成不可变类型的一个重要原因是因为它是编程语言里面使用频率...

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

    final关键字** `final`关键字可以用于类、方法或变量,表示不可改变。当用于类时,意味着该类不能被其他类继承;用于方法时,表示该方法不能被子类重写;用于变量时,表示该变量一旦赋值就不能再次修改。 **5. ...

Global site tag (gtag.js) - Google Analytics