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() {
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?只是语法糖,内部类里面照样不能修改引用,修改导致编译不过的。
**