一、final修饰类
1、被final修饰的类不能再被继承
2、类的所有方法会被隐式的设置为final类型,成员变量不会被隐式设置
3、使用:除非真的该类需要设置为不能被继承,否则需要谨慎设置final类
二、final修饰方法
1、只有在防止子类继承的情况下需要将方法设置为final类型,现在的版本与性能无关(之前性能会加快)。
2、被private修饰的方法,会被隐式的设置为final类型
三、final修饰字段
1、变量类型
1、基本类型
被final类型修饰的基本类型,值不能再改变,即不能再用等号进行赋值。
2、引用类型
被final修饰的引用类型,其实与基本类型一样,不能再通过new进行赋值,但是引用类型的内部字段值还可以更改。
2、局部变量
匿名内部类所引用的外部类的局部变量一定为final类型
3、基本类型和String(常量处理情况)
当final修饰基本类型或String的时候,会被编译器在编译期加载为常量(加载到常量池)。经常看见很多private static final类型的类成员变量,还使用StringBuffer进行append,再用toString()方法处理。其实用String
4、“当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法外的变量”的理解
之前在项目中很多方法内部看见,在入参的前面添加final类型,并不是很理解,但是很多时候可能并不是我们所期望的那样。
1、基本类型
package com.kevin.concurrent;
public class FinalDemoBase {
public static void main(String[] args) {
int i = 1;
doSomething(i);
System.out.println("after doSomething i is " + i);
}
public static void doSomething(int num) {
num = 0;
}
}
调用的结果,跟想象的一样为1。 若用final修饰后,方法内部不能改变入参的值,但是对外部没有任何的影响。
after doSomething i is 1
2、引用类型
只要不是在调用方法后将返回的参数的对象类型,并接收,调用的对象本身没有变。即使将方法的入参用final进行修饰,在方法内部修改了入参对象的字段值,外部的字段值也被改变了。
package com.kevin.concurrent;
public class FinalDemo {
public static void main(String[] args) {
User user = new User();
user.setId(1L);
user.setName("zhangsan");
// 打印当前对象的地址
System.out.println(user);
// 做一些事
doSomething(user);
// 打印调用方法后的当前对象的地址
System.out.println(user);
// 打印调用方法后,对象的字段值,之前设置为“zhangsan”
System.out.println("user name is " + user.getName());
}
public static void doSomething(User user) {
user = new User();
System.out.println("local user is " + user);
// ...
}
public static void doSomething2(final User user) {
// user = new User();
user.setName("lisi");
System.out.println("local user is " + user);
// ...
}
}
调用doSomething()结果:
com.kevin.concurrent.User@4c0bc4
local user is com.kevin.concurrent.User@679bde
com.kevin.concurrent.User@4c0bc4
user name is zhangsan
调用doSomething2()的结果:
com.kevin.concurrent.User@4c0bc4
local user is com.kevin.concurrent.User@4c0bc4
com.kevin.concurrent.User@4c0bc4
user name is lisi