一、概述
1.final修饰类
表示这个类不能被继承,如String,final类中的所有成员方法都会被隐式地指定为final方法。
2.修饰方法
java编程思想:
第一个原因是把方法锁定,以防任何继承类修改它的含义
第二个原因是效率,在早期的java实现版本中,会将final方法转为内嵌调用,但是由于方法过于庞大,可能看不到内嵌调用带来的任何性能提升,在最近的java版本中,不需要使用final方法进行这些优化了。
注:类的private方法会隐式地被指为final。
3.修饰变量
对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象,重新赋值会编译报错,如下。
二、具体讲解
1.类的final变量和普通变量有什么区别?(重点)
java是这样设计的:final一生只认一个值,你初始化好了,他就不能在重新赋值。
当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值。
1.1.下面这个例子是局部变量的例子(final在编译器就确认了值)
public class DemoTest {
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);
System.out.println(a==e);
}
}
1.2.结果
true
false
1.3.下面这个例子是局部变量的例子(final在编译器不能确定getHello())
public class DemoTest {
public static void main(String[] args) {
String a="hello2";
final String b=getHello();
String c=b+2;
System.out.println(a==c);
}
public static String getHello() {
return "hello";
}
}
1.4.结果
false
2.被final修饰的引用变量指向的对象内容可变吗?
内容可变,不变的是地址,记住是地址,这个面试经常考。
3.final和static
3.1.static保证只有独一份。
3.2.final保证值不变,记住引用变量内容是可以变的。
4.匿名内部类中使用的外部局部变量为什么只能是final变量
5.关于final参数的问题
使用final修饰方法参数的目的是防止修改这个参数的值,同时也是一种声明和约定,强调这个参数是不可变的
原因在于java采用的是值传递【这个话题很受争议】,对于引用变量,传递的是引用的值【准确讲是内存里的地址】,也就是说让实参和形参同时指向了同一个对象,因此让形参重新指向另一个对象对实参并没有任何影响。
public class DemoTest {
public static void main(String[] args) {
MyClass myClass = new MyClass();
StringBuffer buffer = new StringBuffer("hello");//实参
myClass.changeValue(buffer);
System.out.println(buffer.toString());
}
}
public class MyClass {
//形参()
void changeValue(StringBuffer buffer){
buffer.append("world");
}
}
这里的buffer.append操作的地址跟实参是同一个,所以结果是hello world.
如果方法changeValue里,buffer=new StringBuffer("诺言");这里只能改变形参的地址,但不能改变实参的地址,所以打印结果是外面的 hello【这地方很容易翻车】
public class MyClass {
//形参()
void changeValue(StringBuffer buffer){
buffer.append("world");
buffer=new StringBuffer("诺言");//形参值被改变,但不影响实参
System.out.println(buffer); //诺言
}
}
最后输出的还是 hello world
实参和形参【科普】
1、形参变量只有在被调用时才分配内存单元,在调用结束时,就会释放出所分配的内存单元。所以,形参只能在函数内部才有效;【生存周期在方法内】
2、实参是:常量、变量、表达式、函数等,实参是何种类型的量,当开始在进行函数调用时,都必须有确定的值;【实参复杂值给形参】
3、在一般传值调用的机制中只能把实参传送给形参,因此在函数调用过程中,形参值发生改变,而实参中的值不会变化。【很重要】
三、结束
Always keep the faith!!!