匿名内部类为什么要是final?

1. java 是引用传参。在里面是修改不了的。

Java8

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
public class FinalTest {

public static void changeStr(String string){
string = "BBBB";
}

public static void testInterface(TestInterface testInterface){
testInterface.say();
}
public static void main(String[] args) {
String string = "AAAA";
//这个是改不了的
changeStr(string);
System.out.println(string);

testInterface(new TestInterface() {
@Override
public void say() {
/*
如果可以,这个改得了吗?
string = "CCCCC";
*/
System.out.println(string);
}
});
}
}


interface TestInterface{
void say();
}

2.如果在匿名内部内里面 可以修改?

你觉是改了外部类的引用,还是没改呢?按写代码的思路,你可能认为给改了,因为这不是方法的传参。但实际上呢?会产生歧义。

3.匿名内部类引用外部变量 实际上是拷贝的引用。同方法的传参。

java为了保持数据的一致性。不让在内部类里面修改。因为编译阶段就处理了,匿名内部类因引用的外部变量,在匿名对象构造时候,以构造参数形式传入的。
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// class version 52.0 (52)
// access flags 0x21
public class test/FinalTest {

// compiled from: FinalTest.java
// access flags 0x8
static INNERCLASS test/FinalTest$1 null null

// access flags 0x1
public <init>()V
L0
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Ltest/FinalTest; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1

// access flags 0x9
public static changeStr(Ljava/lang/String;)V
L0
LINENUMBER 6 L0
LDC "BBBB"
ASTORE 0
L1
LINENUMBER 7 L1
RETURN
L2
LOCALVARIABLE string Ljava/lang/String; L0 L2 0
MAXSTACK = 1
MAXLOCALS = 1

// access flags 0x9
public static testInterface(Ltest/TestInterface;)V
L0
LINENUMBER 10 L0
ALOAD 0
INVOKEINTERFACE test/TestInterface.say ()V (itf)
L1
LINENUMBER 11 L1
RETURN
L2
LOCALVARIABLE testInterface Ltest/TestInterface; L0 L2 0
MAXSTACK = 1
MAXLOCALS = 1

// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 13 L0
LDC "AAAA"
ASTORE 1
L1
LINENUMBER 15 L1
ALOAD 1
INVOKESTATIC test/FinalTest.changeStr (Ljava/lang/String;)V
L2
LINENUMBER 16 L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L3
LINENUMBER 18 L3
NEW test/FinalTest$1
DUP
ALOAD 1

//看这里,看这里 <init> 方法多了一个String
// 匿名内部类因引用的外部变量,在匿名对象构造时候,以构造参数形式传入的
INVOKESPECIAL test/FinalTest$1.<init> (Ljava/lang/String;)V
INVOKESTATIC test/FinalTest.testInterface (Ltest/TestInterface;)V
L4
LINENUMBER 28 L4
RETURN
L5
LOCALVARIABLE args [Ljava/lang/String; L0 L5 0
LOCALVARIABLE string Ljava/lang/String; L1 L5 1
MAXSTACK = 3
MAXLOCALS = 2
}

4.为什么?

因为匿名内部类 引用外部类的变量 是隐式的类似方法的传参。关键是隐式的处理,若果可以改,必定是改不了外部引用的,防止产生歧义。为什么Java8 不需要加final?只是语法糖,内部类里面照样不能修改引用,修改导致编译不过的。
**