Java 关键字final的用途是什么?
在下面的代码中,如果我从EditText中删除关键字final,我将在第(6)行中出现获取错误,在该行中我将EditText对象(et)传递给intent…我必须在此处了解final关键字的重要性Java 关键字final的用途是什么?,java,android,final,Java,Android,Final,在下面的代码中,如果我从EditText中删除关键字final,我将在第(6)行中出现获取错误,在该行中我将EditText对象(et)传递给intent…我必须在此处了解final关键字的重要性 final EditText et=(EditText)findViewById(R.id.t); Button b=(Button)findViewById(R.id.b1); b.setOnClickListener(new Button.OnClickListen
final EditText et=(EditText)findViewById(R.id.t);
Button b=(Button)findViewById(R.id.b1);
b.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v)<br>
{
Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText()));
startActivity(on);
}
});
final EditText et=(EditText)findViewById(R.id.t);
按钮b=(按钮)findViewById(R.id.b1);
b、 setOnClickListener(新建按钮。OnClickListener(){
单击“公共无效”(视图v)
{
Intent on=newintent(Intent.ACTION_调用,Uri.parse(“tel:+et.getText()));
星触觉(on);
}
});
这是因为您在这里使用闭包。这意味着内部类使用内置类的上下文。要使用它,变量应该声明为final,以便不被更改
请参阅更多。Final使变量et只允许分配一次。它还改变了变量的范围,并允许函数onClick对et的可见性。如果没有final,et在函数onClick中不可见。final本质上意味着变量
et
在任何时候都不会被重新分配,并且会保留在附近。这意味着内部类,如侦听器,可以相信它不会被其他线程重新分配,这可能会导致各种各样的问题
final还可用于修改方法或类定义,这意味着该方法不能被子类重写,或者该类不能扩展。其中讨论了final
关键字。根据(第4.12.4节):
变量可以声明为final。最后一个变量只能指定一次。如果将最终变量赋值给,则为编译时错误,除非在赋值之前明确未赋值(§16)
阅读以了解所涉及的实施细节:
这项限制的原因是什么
如果我们能弄清楚的话
关于如何实现本地类。
匿名本地类可以使用本地
因为编译器
自动给班级a
保存副本的专用实例字段
类使用的每个局部变量的。
编译器还添加了隐藏的
每个构造函数的参数
初始化这些自动创建的
私人领域。因此,本地类
实际上不访问本地
变量,但仅仅是它自己的私有
它们的副本。只有这样才能
正确工作是如果本地
变量被声明为final,因此
他们保证不会改变。
有了这一保证
本地类确信其
变量的内部副本
准确反映当地的实际情况
变量
编辑:
Berlin Brown说:“我发布了一个 匿名的内部类。但是 老实说,我还是不明白为什么 编译器必须有这些信息。 即使该字段被宣布为最终字段, 该字段仍然可以为空。我认为 你知道,这是Java的怪癖之一 必须声明该字段 最后…因为这就是它的方式。 没有一个明确的理由来解释为什么” 原因是要确保用户意识到闭包“关闭”变量而不是值。让我们假设不需要有最终的局部变量。然后我们可以编写如下代码:
public void doIt() {
for(int i = 0; i < 3; ++i) {
runnables.add(new Runnable() {
@Override
public void run() {
System.out.println(i);
}
});
}
run(runnables); // run each runnable
}
public void doIt(){
对于(int i=0;i<3;++i){
添加(新的Runnable(){
@凌驾
公开募捐{
系统输出打印LN(i);
}
});
}
运行(可运行);//运行每个可运行
}
你认为结果会是什么?如果您认为它是“0 1 2”,那么您就错了,因为Runnable在该时间点关闭“变量”i而不是i的“值”,因此输出将是“2 2”。在这里可以做些什么来实现预期的行为?两种解决方案:要么依靠用户了解闭包是如何工作的,要么以某种方式在语言级别实施闭包。这是语言设计师们的第二个选择
public void doIt() {
for(int i = 0; i < 3; ++i) {
final int j = i; // notice the final local variable
runnables.add(new Runnable() {
@Override
public void run() {
System.out.println(j);
}
});
}
run(runnables);
}
public void doIt(){
对于(int i=0;i<3;++i){
final int j=i;//注意最后一个局部变量
添加(新的Runnable(){
@凌驾
公开募捐{
系统输出println(j);
}
});
}
运行(可运行);
}
JFTR,我并不是说第二种选择是“正确的”方法,只是在匿名内部类中使用局部变量之前将其标记为final对我来说是一个大问题。当然,YMMV.:-) 它还有助于理解Java如何创建匿名内部类。Java如何实现该特定类 Java需要该变量为final,因为编译器必须在编译时知道该对象的类型。然后,编译器将在匿名内部类实现中生成一个字段(在本例中为“et”) 如果类型不是final,编译器将如何确定如何构建内部类实现。基本上,通过声明字段final,您为Java编译器提供了更多信息 对编译器没有帮助的代码不会编译匿名内部类:
Object et;
et = a ? new Object() : new EditText();
使用上面的代码,Java编译器无法真正构建匿名内部类
您的代码:
Object et;
et = a ? new Object() : new EditText();
最终编辑文本et=(编辑文本)findViewById(R.id.t)
new按钮。OnClickListener$1(){
单击“公共无效”(视图v)
{
Intent on=newintent(Intent.ACTION_调用,Uri.parse(“tel:+et.getText()));
星触觉(on);
}
});
。。。
java编译器将创建一个字节码类,这是您提供的内部类块的一个实现,可能如下所示
public class OnClickListener$1 {
private final EditText et ; <---- this is important
public OnClickListener$1(final et) {
this.et = et;
}
public void onClick(View v)<br>
{
Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText()));
startActivity(on);
}
}
公共类OnClickListener$1{
私人最终编辑文本et;的目的
Java final variable: If you make any variable as final, you cannot change the value of final variable (It will be constant).
Java final method: If you make any method as final, you cannot override it.
Java final class: If you make any class as final, you cannot extend it.