代码之家  ›  专栏  ›  技术社区  ›  Tom

内部类是否可以引用Java 8中在外部类中定义的非最终变量

  •  2
  • Tom  · 技术社区  · 3 年前

    我一直认为内部类不能引用外部类中定义的非最终变量。

    但是,当我编写以下代码时,它会正确编译,并且可以在Intellij Idea中运行。

    为什么以下代码有效?

    public class Outer {
    
        /**
         * non final variable greeting is used in inner class, non final is OK?
         */
        private String greeting = "Greeting1";
    
        /**
         * non final variable s is used in inner class, non final is OK?
         */
        public String doWork(String s) {
            class Inner {
                public String speak(String ss) {
                    return greeting + "--- " + s + "---" + ss;
                }
            }
            Inner obj = new Inner();
            return obj.speak("Inner");
        }
    
        public static void main(String[] args) {
            Outer obj = new Outer();
            //Can assign here.
            obj.greeting="Greeting2";
            System.out.println(obj.doWork("Outer"));
        }
    }
    
    1 回复  |  直到 2 年前
        1
  •  4
  •   Sweeper    3 年前

    这个 Java Language Specification 说:

    内部类中使用但未声明的任何局部变量、形式参数或异常参数都必须声明为final或实际上是final( §4.12.4 ),或者在尝试使用时发生编译时错误。

    你很可能回忆起了不正确的版本。你可能误以为:

    任何 实例变量 ,内部类中使用但未声明的局部变量、形式参数或异常参数必须声明为final 或者实际上是最终的( §4.12.4 ) ,或者在尝试使用时发生编译时错误。

    greeting 是一个字段(也称为实例变量),因此无论它是否为final,都可以在内部类中使用。

    ss ,虽然它是一个形式参数,但为 实际上是最终的 ,所以它也可以在内部类中使用。请注意,短语“实际上是最终的”在中有一个正式定义 §4.12.4 ,但非正式地说,在这种情况下,它只是意味着“您没有在该方法中为其重新分配另一个值”。

    看看这个 post 为什么存在这种限制。