Final主要应用场合:数据、方法以及类。
final数据:
(1) 编译期常数,它永远不会改变。
(2) 在运行期初始化的一个值,我们不希望它发生变化。
对于编译期的常数,编译器(程序)可将常数值“封装”到需要的计算过程里。也就是说,计算可在编译期间提前执行,从而节省运行时的一些开销。在Java 中,这些形式的常数必须属于基本数据类型。
无论static 还是final 字段,都只能存储一个数据,而且不得改变。
(1)对于基本数据类型,final 会将值变成一个常数。
(2)对于对象,final 会将句柄变成一个常数。进行声明时,必须将句柄初始化到一个具体的对象。而且永远不能将引用变成指向另一个对象。然而,对象本身是可以修改的。
1、final数值常量:
public static final double PI = 3.14
final 属性的基本数据类型,并含有编译期的值,所以它们除了能作为编译期的常数
使用外,在任何导入方式中也不会出现任何不同。Static 强调它们只有一个;而final 表明它是一个常数。
final static表示编译期的常数。
2、空白final:
private final List list;
private final Sudent sudent;
尽管被声明成final,但却未得到一个初始值。无论在哪种情况下,空白final 都必须在实际使用前得到正确的初始化。而且编译器会主动保证这一规定得以贯彻。然而,对于final 关键字的各种应用,空白final 具有最大的灵活性。位于类内部的一个final 字段现在对每个对象都可以有所不同,同时依然保持其“不变”的本质。
3、final自变量:
public int getNext(final int index) {}
只能读取自变量,不可改变它,对象只能读取该对象,对象的值还是可以改变的。
总结:final变量,其实声明为final表示指向对象的引用就不能改变了,如果是指向基本类型,基本就是常量,如果是对象,从头到尾都表示只是一个对象,对象的属性内容可以改变。
final方法:
public final String getMethodName() {};
声明为final的方法条件
1、设计足够完美,防止任何继承类改变它的本来含义。
2、效率的考虑。只要编译器发现一个final方法调用,就会忽略为执行方法调用机制而采取的常规代码插入方法(将自变量压入堆栈;跳至方法代码并执行它;跳回来;清除堆栈自变量;最后对返回值进行处理)。相反,它会用方法主体内实际代码的一个副本来替换方法调用。这
样做可避免方法调用时的系统开销。
private是之后自己才能使用,继承不了,声明为final,子类还是可以调用的,只是不能重写。
final类:
final class TestFinalClass{}。
典型的有String Integer Long等。
如果说整个类都是final,就表明自己不希望从这个类继承,或者不允许其他任何人采取这种操作。换言之,出于这样或那样的原因,我们的类肯定不需要进行任何改变;或者出
于安全方面的理由,我们不希望进行子类化(子类处理)。
数据成员既可以是final,也可以不是,final的规则同样适用于数据成员,无论类是否被定义成final,类定义成final 后,结果只是禁止进行继承——没有更多的限制。然而,由于它禁止了继承,所以一个final 类中的所有方法都默认为final。因为此时再也无法覆盖它们。所以与我们将一个方法明确声明为final一样,编译器此时有相同的效率选择。
import java.util.ArrayList;
import java.util.List;
/**
* 功能描述:JAVA Final测试
* Date: 13-1-28 Time:下午7:37
*/
public class TestFinal {
/**
* final常量
*/
public static final double PI = 3.14;
/**
* final类变量
*/
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* final数值,空白final
*/
final String className;
final TestFinalMethod testFinalMethod;
final List list;
/**
* 传入参数初始化final
* @param className
* @param testFinalMethod
* @param list
*/
public TestFinal(String className, TestFinalMethod testFinalMethod, List list) {
this.className = className;
this.testFinalMethod = testFinalMethod;
this.list = list;
}
/**
* 构造初始化空白final
*/
public TestFinal() {
className = TestFinal.class.getName();
testFinalMethod = new TestFinalMethod();
list = new ArrayList();
}
/**
* final变量参数
* @param index
* @return
*/
public int getFinalCount(final int index) {
int num = 0;
for (int i = 0; i < 100; i++) {
// index ++;
num = num + index;
}
return num;
}
/**
* 修改final变量参数
*/
public void modifyFinalParams() {
list.add("abc");
list.add(10);
testFinalMethod.setKey("key");
testFinalMethod.setValue(100);
}
}
/**
* 测试Final方法
*/
//class TestFinalMethod extends TestFinalClass {
class TestFinalMethod {
private String key;
private int value;
/**
* final方法
*/
public final String getTestFinalMethodName() {
return TestFinalMethod.class.getName();
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
/**
* 测试Final类
*/
final class TestFinalClass {
private String className;
public String simpleName;
public final String getTestFinalClassName() {
return TestFinalMethod.class.getName();
}
}