Java:使用局部变量的匿名内部类

Ale*_*yne 9 java scope anonymous-class

如何userId在我的匿名内部子类中获取传递给此方法的值?

public void doStuff(String userID) {
    doOtherStuff(userID, new SuccessDelegate() {
        @Override
        public void onSuccess() {
            Log.e(TAG, "Called delegate!!!! "+ userID);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

不能在不同方法中定义的内部类中引用非最终变量userID

我很确定我不能将它指定为final,因为它是一个具有未知值的变量.我听说这种语法确实以某种方式保留了范围,所以我认为必须有一个我还不太了解的语法技巧.

Tof*_*eer 11

正如这里的其他人所说的那样,局部变量必须是内部类才能访问的最终变量.

这里(基本上)是为什么......如果你写下面的代码(长答案,但是,在底部,你可以得到短版本:-):

class Main
{
    private static interface Foo
    {
        void bar();
    }

    public static void main(String[] args)
    {
        final int x;
        Foo foo;

        x = 42;
        foo = new Foo()
        {
            public void bar()
            {
                System.out.println(x);
            }
        };

        foo.bar();
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器大致翻译它:

class Main
{
    private static interface Foo
    {
        void bar();
    }

    public static void main(String[] args)
    {
        final int x;
        Foo foo;

        x = 42;

        class $1
            implements Foo
        {
            public void bar()
            {
                System.out.println(x);
            }
        }

        foo = new $1();
        foo.bar();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后这个:

class Main
{
    private static interface Foo
    {
        void bar();
    }

    public static void main(String[] args)
    {
        final int x;
        Foo foo;

        x = 42;
        foo = new $1(x);
        foo.bar();
    }

    private static class $1
        implements Foo
    {
        private final int x;

        $1(int val)
        {
           x = val;
        }

        public void bar()
        {
            System.out.println(x);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后到此:

class Main
{
    public static void main(String[] args) 
    {
        final int x;
        Main$Foo foo;

        x = 42;
        foo = new Main$1(x);
        foo.bar();
    }
}

interface Main$Foo
{
    void bar();
}

class Main$1
    implements Main$Foo
{
    private final int x;

    Main$1(int val)
    {
       x = val;
    }

    public void bar()
    {
        System.out.println(x);
    }
}
Run Code Online (Sandbox Code Playgroud)

重要的是它将构造函数添加到$ 1.想象一下,如果你能做到这一点:

class Main
{
    private static interface Foo
    {
        void bar();
    }

    public static void main(String[] args)
    {
        int x;
        Foo foo;

        x = 42;
        foo = new Foo()
        {
            public void bar()
            {
                System.out.println(x);
            }
        };

        x = 1;

        foo.bar();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能希望foo.bar()打印出1,但它实际上会打印出来.通过要求局部变量为最终,这种混乱的情况不会出现.


And*_*yle 7

当然你可以将它指定为final - 只需将该关键字放在参数的声明中:

public void doStuff(final String userID) {
   ...
Run Code Online (Sandbox Code Playgroud)

我不确定你是什么意思,它是一个具有未知值的变量; 所有这一切最终意味着,一旦为变量赋值,就无法重新分配.由于您没有在方法中更改userID的值,因此在这种情况下将其设置为final是没有问题的.