我是靠谱客的博主 现实犀牛,这篇文章主要介绍final关键字的多种用法,现在分享给大家,希望可以做个参考。

(一)final用于修饰类中的属性

final的基础知识:

Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量

带有恒定初始值的final static基本类型全用大写字母命名,并且字与字之间用下划线隔开。

1.final类不能被继承,没有子类,final类中的方法默认是final的。
2.final方法不能被子类的方法覆盖,但可以被继承。
3.final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
4.final不能用于修饰构造方法。

思考问题:

1.被final修饰的所有属性真的是在编译时就可以知道它的值么?

2.被final static修饰和被final修饰有什么区别?

3.空final有什么用处呢?

4.用final修饰引用类型和基本数据类型又有什么不同点?

先看下面的代码,猜猜i4和INT_5的值会不会改变?如果把其中注释掉的代码给解除注释代码还能不能正常运行?

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class Value{ int i; public Value(int i){ this.i = i; } } public class Demo6 { private final int j; private final Value value; private static Random rand = new Random(47); private String id; public Demo6(){ value = new Value(1); j = 1; } public Demo6(String id){ this.id = id; value = new Value(0); j = 0; } public Demo6(int j){ this.j = j; value = new Value(j); } private final int valueOne = 9; private static final int VALUE_TOW = 99; public static final int VALUE_THREE = 39; private final int i4= rand.nextInt(20); static final int INT_5 = rand.nextInt(20); private Value v1 = new Value(11); private final Value v2 = new Value(22); private static final Value VAL_3 = new Value(33); private final int[] a = {1,2,3,4,5,6}; public String toString(){ return id+":"+"i4 = "+i4+", INT_5 = "+INT_5; } public static void main(String[] args) { Demo6 fd1 = new Demo6("fd1"); // fd1.valueOne++; fd1.v2.i++; fd1.v1 = new Value(9); for(int i=0;i<fd1.a.length;i++){ fd1.a[i]++; } // fd1.v2 = new Value(0); // fd1.VAL_3 = new Value(1); // fd1.a = new int[3]; System.out.println(fd1); System.out.println("Creating new Demo6"); Demo6 fd2 = new Demo6("fd2"); System.out.println(fd1); System.out.println(fd2); } }

输出结果:

复制代码
1
2
3
4
5
fd1:i4 = 15, INT_5 = 18 Creating new Demo6 fd1:i4 = 15, INT_5 = 18 fd2:i4 = 13, INT_5 = 18

总结:

1.当我们使用final常量时并不能单纯的认为在编译时就可以知道他的值,在运行时通过随机生成的数值来初始化i4和INT_5就可以得出这个结论

2.只用final修饰的常量在当前对象的值是唯一的,但是当我们在创建一个对象时final的值是可以初始化不同的值的.

3.被final修饰的引用,只是说明引用的指向不能被改变,但是其对象本身是可以被改变的,通过上面代码的int类型的数组的值被改变就可以发现

4.空白final是指被声明为final但又未给定初值的域,无论什么属性,编译器都要确保空白final在被使用前被初始化,不信可以试试把构造器中对空白final初始化的代码注释掉试试

5.在构造器中对空白final进行初始化,可以让不同的对象有不同的final值,并且保持final恒定不变的特性,这就是为什么说final的值并不是固定的原因了。

6.static final用来修饰成员变量和成员方法,可简单理解为“全局常量”。对于变量,表示一旦给值就不可修改,并且通过类名可以访问。对于方法,表示不可覆盖,并且可以通过类名直接访问。

(二)final用于修饰类中的方法

思考一下能不能继承父类的private方法或者final方法?

当你重写父类的private方法时,真的是重写么?

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class WithFinals{ private final int i = 19; public int getI(){ return i; } private final void f(){ System.out.println("WithFinals.f()"); } private void g(){ System.out.println("WithFinals.g()"); } } class OverridingPrivate extends WithFinals{ // @Override private void f(){ System.out.println("OverridingPrivate.f()"); } private void g(){ System.out.println("OverridingPrivate.g()"); } } class OverridingPrivate2 extends OverridingPrivate{ // @Override public final void f(){ System.out.println("OverridingPrivate2.f()"); } public void g(){ System.out.println("OverridingPrivate2.g()"); } } public class Demo7 { public static void main(String[] args) { OverridingPrivate2 op2 = new OverridingPrivate2(); op2.f(); op2.g(); System.out.println(op2.getI()); OverridingPrivate op = op2; // op.f(); // op.g(); WithFinals wf = op2; // wf.f(); // wf.g(); } }

输出结果:

复制代码
1
2
3
OverridingPrivate2.f() OverridingPrivate2.g() 19

 其实子类确实继承了父类的私有方法和属性,不然又怎么调用父类的方法去操纵父类的私有属性呢。

代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; class Father { private String name = "father"; public Father(){ } private void printf(){ System.out.println("father方法"); } } class Test extends Father{ } public class Demo8 extends Father{ public static void main(String[] args) throws Exception{ Class c = Test.class; Test test = new Test(); Class f = c.getSuperclass(); Method[] declaredMethods = f.getDeclaredMethods(); AccessibleObject.setAccessible(declaredMethods,true); for(Method m :declaredMethods){ System.out.println("子类调用父类的"+m.getName()+"方法"); m.invoke(test); } } }

输出结果:

复制代码
1
2
3
子类调用父类的printf方法 father方法

通过反射可以看到子类确实继承了父类的private方法,只是因为访问权限的问题不能对私有的方法进行访问,当你用private和final同时修饰类中的方法时,你会发现编译器发出警告(private被声明为final)这也就间接的说明了其实private方法是被隐式的指定为final的,只是因为无法取用private方法所以没办法覆盖它,当然你也可以加上final修饰符,但是这个修饰符其实没有发挥任何意义。

方法可以声明为 final 方法,以防止子类覆盖或隐藏它。尝试重写或隐藏最终方法是编译时错误。
私有方法和在最终类中立即声明的所有方法的行为就像它们是最终方法一样,因为不可能重写它们,但是final方法可以在子类中用super调用,而private方法不可以在子类中调用。

(三)final参数

当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。

复制代码
1
2
3
4
5
6
7
8
9
10
public class Test4 {         public static void main(String[] args) {                 new Test4().f1(2);         }         public void f1(final int i) {                 //i++;    //i是final类型的,值不允许改变的.                 System.out.print(i);         } }

参考资料:Java关键字final、static使用总结_熔 岩的技术博客_51CTO博客

最后

以上就是现实犀牛最近收集整理的关于final关键字的多种用法的全部内容,更多相关final关键字内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(73)

评论列表共有 0 条评论

立即
投稿
返回
顶部