final:
1.修饰类:
当用final修饰一个类时,表明这个类不能被继承,如果一个类永远不会让他被继承,可以用final来修饰,成员变量可以按需要定义成final,但要注意final类中所有的成员方法都会被隐式地指定为final方法。
在使用final修饰类是需要谨慎考虑,除非这个类以后真的不会用来被继承或者出于安全考虑,否则尽量不要将类设计为final类。
2.修饰方法:
1.锁定方法,以防任何继承类修改此方法的含义。
2.效率,在早起的java实现版本中,会将final方法转为内嵌调用,但是如果方法过于庞大,可能看不到内嵌调用带来任何性能提升,在最近的java版本中,不需要使用final方法进行这些优化了。
(注:1.只有在想明确禁止该方法在子类中被覆盖的情况下才将方法设置为final。
2.类的private方法会隐式地被指定为final方法。)
3.修饰变量
对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后就不能修改;
如果是引用类型的变量(类变量),则在对其初始化之后边不能再让其指向另一个对象。
深入了解:
1.当final作用于类的成员变量时,成员变量必须在定义时或者构造器中进行初始化赋值(因为其他子类或方法不能再对其进行修改或者覆盖),当final作用于局部变量时,只要保证在使用之前被初始化赋值即可。
2.当final作用于基本数据类型或者String类型的变量时,如果能在编译过程中知道该变量的确切值,则编译器会把他当作编译期的常量使用,也就是说在用到该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));// true
System.
out
.println((a == e));// 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));
// false
}
public
static
String getHello() {
return
"hello"
;
}
}
3.如果final修饰引用类型的变量(类变量),则在对其初始化之后边不能再让其指向另一个对象,但是该引用变量指向的对象内容可变。
4.static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变
例如:
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的值却是不同的。
5. 匿名内部类中使用的外部局部变量只能是final变量。
(题外话:
代码中的实例变量、类变量、常量都属于成员变量,与局部变量的区别就是private、static、final等修饰符
)
参考网址: