Java 在方法内声明类-Final关键字

Java 在方法内声明类-Final关键字,java,Java,给定方法中的以下内部类(IsSomething): public class InnerMethod { private int x; public class Something { private int y; public void printMyNumber(double x) { class IsSomething extends Something { public void print() {

给定方法中的以下内部类(IsSomething):

public class InnerMethod {

private int x;


public class Something {
    private int y;

    public void printMyNumber(double x)
    {
        class IsSomething extends Something {

            public void print() {
                System.out.println(x);
            }

        }
    }
}

}
为什么X变量必须是最终变量才能工作。。?
(我指的是“printMyNumber”函数的X参数。)

匿名类中的方法实际上无法访问局部变量和方法参数。相反,当实例化匿名类的对象时,对象的方法引用的最终局部变量和方法参数的副本作为实例变量存储在对象中。匿名类的对象中的方法实际上访问那些隐藏的实例变量

联合联络小组:


在内部类中使用但未声明的任何局部变量、形式方法参数或异常处理程序参数必须声明为final。在内部类中使用但未声明的任何局部变量必须在内部类主体之前明确赋值(§16)。

局部变量与类成员变量之间的差异。成员变量在封闭对象的生存期内存在,因此内部类实例可以引用它。但是,局部变量仅在方法调用期间存在,编译器处理方式不同,因为它的隐式副本是作为内部类的成员生成的。在不声明局部变量final的情况下,可以对其进行更改,从而导致细微的错误,因为内部类仍然引用该变量的原始值

我知道创建局部变量或局部变量有两个原因 最终参数。第一个原因是你不想要你的代码 更改局部变量或参数。许多人认为这是一个错误 在方法中更改参数的方式可能不好,因为它会使 代码不清楚。作为一种习惯,一些程序员会制作他们所有的参数 “最终”以防止自己改变它们。我不这么做, 因为我发现它使我的方法签名有点难看

第二个原因是当我们想要访问局部变量或 内部类中的参数。这才是真正的原因 据我所知,最终的局部变量和参数是 在JDK1.1中引入Java语言

在run()方法内部,只有在外部类中将i设为final时,才能访问i。要理解原因,我们必须

看看编译器是做什么的。它生成两个文件,Access1.class 和Access1$1.5等级。当我们用JAD反编译它们时,我们得到:

由于i的值是final,编译器可以将其“内联”到内部

班级。局部变量必须是最终的,这让我很不安 被内部类访问,直到我看到上面的内容

当局部变量的值可以为不同的 内部类的实例,编译器将其添加为 内部类,并允许在构造函数中对其进行初始化。这个 这背后的根本原因是Java没有指针 C的方式

考虑以下类别:

公共类访问2{
公共空间f(){

对于(int i=0;i,这是因为本地类实例的生存期可能比定义该类的方法的执行时间长得多。因此,本地类必须具有其使用的所有本地变量的私有内部副本(这些副本由编译器自动生成)。确保局部变量和私有副本始终相同的唯一方法是坚持局部变量是final。

因此,将其声明为final。编译器做什么?保留它..?它不会在函数作用域末尾被销毁吗?全部读取:)很好。关于这一行:System.out.println(3);它真的用3替换了I final变量吗?内联吗?@Rouki我不认为它用3替换了I。final允许Java编译器“捕获”运行时变量的值,并将副本作为字段存储在内部类中。好的,因此编译器会将最终变量保留在当前对象中。对吗?该值会复制到匿名内部类的实例中,因此一旦复制了方法内部但类外部的代码,就不应该修改它,或者不会修改值n sync.非主题问题。内部类是否会自动扩展其中的类?不,它们是完全不同的概念。@noob:我想问一下外部类的扩展是如何工作的,就像在这个问题中一样?我的意思是内部类如何能够在外部类中定义自己。?
public class Access1 {
  public void f() {
    final int i = 3;
    Runnable runnable = new Runnable() {
    public void run() {
      System.out.println(i);
    }
    };
  }
}
public class Access1 {
  public Access1() {}
  public void f() {
    Access1$1 access1$1 = new Access1$1(this);
  }
}
class Access1$1 implements Runnable {
  Access1$1(Access1 access1) {
    this$0 = access1;
  }
  public void run() {
    System.out.println(3);
  }
  private final Access1 this$0;
}
public class Access2 {
  public void f() {
    for (int i=0; i<10; i++) {
    final int value = i;
    Runnable runnable = new Runnable() {
      public void run() {
        System.out.println(value);
      }
    };
    }
  }
} 
public class Access3 {
  public void f() {
    Runnable[] runners = new Runnable[10];
    for (final int[] i={0}; i[0]<runners.length; i[0]++) {
    runners[i[0]] = new Runnable() {
      private int counter = i[0];
      public void run() {
        System.out.println(counter);
      }
    };
    }
    for (int i=0; i<runners.length; i++)
    runners[i].run();
  }
  public static void main(String[] args) {
    new Access3().f();
  }
}