关键字final有什么用?

发布于 2024-10-09 18:34:47 字数 501 浏览 12 评论 0原文

在下面的代码中,如果我从 EditText 中删除关键字 Final,我会在第 (6) 行中出现错误,其中我将 EditText 对象 (et) 传递给意图...我必须知道这里 Final 关键字的重要性...

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);
            }
        });

In the below code if i remove the keyword final from EditText i am an getting error in the line (6) where i pass EditText object (et) to the intent...I have to knw the significance of final keyword here...

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);
            }
        });

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

岁月染过的梦 2024-10-16 18:34:47

Final本质上意味着变量et在任何时候都不会被重新分配并且将保留下来。这意味着内部类(例如您的侦听器)可以相信它不会被其他线程重新分配,这可能会导致各种麻烦。

Final 还可以用于修改方法或类定义,这意味着该方法不能被子类覆盖,或者该类不能扩展。

Final essentially means that the variable et will not be reassigned at any point and will remain around. This means that inner classes, like your listener, can trust that it wont be reassigned by some other thread which could cause all kinds of trouble.

final can also be used to modify a method or class definition, that would mean that the method can't be overriden by a subclass, or that the class cannot be extended.

白昼 2024-10-16 18:34:47

这是因为你在这里使用了闭包。这意味着内部类使用入界类的上下文。要使用它,变量应该声明为final,以免被更改。

请参阅此处了解更多信息。

It is because you use closure here. It means that inner class uses the context of the inbounded one. To use it the variables should be declared final in order not to be changed.

See more here.

ま柒月 2024-10-16 18:34:47

JAVA中“final”关键字的用途可以定义为三个层次:类、方法、变量

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.

The purpose of “final” keyword in JAVA can be defined in three level are Class, Method, variable

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.
若言繁花未落 2024-10-16 18:34:47

Final 使得变量 et 只允许被赋值一次。它还更改变量的范围并允许函数 onClick 对 et 可见。如果没有final,et 在onClick 函数中不可见。

Final makes the variable et only allowed to be assigned once. It also changes the scope of the variable and allows the function onClick visibility to et. Without the final, et is not visible within the function onClick.

一笔一画续写前缘 2024-10-16 18:34:47

阅读本文了解所涉及的实现细节:

此限制的原因
如果我们阐明一些观点就会变得显而易见
关于如何实施本地课程。
匿名本地类可以使用 local
变量,因为编译器
自动给班级一个
用于保存副本的私有实例字段
类使用的每个局部变量。
编译器还添加了隐藏
每个构造函数的参数
初始化这些自动创建的
私人领域。因此,本地类
实际上并没有访问本地
变量,但仅仅是它自己的私有变量
它们的副本。唯一的办法就是这个
正常工作是如果本地
变量被声明为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
}

:你认为会是输出吗?如果你认为它会是“0 1 2”,那么你就错了,因为 Runnable 在“变量” i 上关闭,而不是在该时间点 i 的“值”,因此输出应该是“2 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);
}

JFTR,我并不是说第二个选项是“最好的”方法,只是在匿名内部类中使用之前将局部变量标记为 Final 是一个大问题。当然是我。:-)

Read this article to understand the implementation details involved:

The reason for this restriction
becomes apparent if we shed some light
on how local classes are implemented.
An anonymous local class can use local
variables because the compiler
automatically gives the class a
private instance field to hold a copy
of each local variable the class uses.
The compiler also adds hidden
parameters to each constructor to
initialize these automatically created
private fields. Thus, a local class
does not actually access local
variables, but merely its own private
copies of them. The only way this can
work correctly is if the local
variables are declared final, so that
they are guaranteed not to change.
With this guarantee in place, the
local class is assured that its
internal copies of the variables
accurately reflect the actual local
variables.

EDIT:

Berlin Brown says: "I posted a decompiled version of an
anonymous inner class. But to be
honest, I still don't see why the
compiler has to have that information.
Even if the field is declared final,
the field can still be null. I think
this is one of those Java quirks, you
have to declare that field
final...because that is the way it is.
There isn't a clear reason why"

The reason is to make sure that users realize that closures "close over" variables and not values. Let's suppose that there was no requirement of having final local variables. Then we could write code like:

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
}

What do you think would be the output? If you think it would be "0 1 2" you would be mistaken since the Runnable closes over the "variable" i and not the "value" of i at that point in time and hence the output would be "2 2 2". What can be done to achieve the expected behaviour here? Two solutions: either rely on the users to have an understanding of how closures work or somehow enforce it at the language level. And it is the second option with which the language designers have gone with.

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);
}

JFTR, I'm not saying that the second option is "the" way to go, it's just that having local variables marked as final before being used in anonymous inner classes is a big deal breaker for me. Of course, YMMV. :-)

千年*琉璃梦 2024-10-16 18:34:47

这是一个讨论 的链接Final 关键字。根据规范(第 4.12.4 节):

变量可以声明为final。最终变量只能分配一次。如果分配了最终变量,则会出现编译时错误,除非在分配之前立即明确未分配该变量(第 16 节)。

Here is a link which discusses the final keyword. According to the specification (section 4.12.4):

A variable can be declared final. A final variable may only be assigned to once. It is a compile time error if a final variable is assigned to unless it is definitely unassigned (§16) immediately prior to the assignment.

何处潇湘 2024-10-16 18:34:47

它还有助于理解 Java 如何创建匿名内部类。 Java 如何实现该特定类。

Java 需要该变量是最终变量,因为编译器必须在编译时知道该对象的类型。然后,编译器将在匿名内部类实现中生成一个字段(在本例中为“et”)。

如果类型不是最终类型,编译器将如何确定如何构建内部类实现。基本上,通过将字段声明为 Final,您可以向 Java 编译器提供更多信息。

对编译器没有帮助的代码,不会编译你的匿名内部类:

Object et;
et = a ? new Object() : new EditText();

...

通过上面的代码,Java编译器无法真正构建匿名内部类。

您的代码:

Final EditText et=(EditText)findViewById(R.id.t);

……

new Button.OnClickListener$1(){
            public void onClick(View v)<br>
            {
            Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText()));
            startActivity(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);
                }
}

您可以通过查找匿名字节码类 $1 并反编译该字节码文件来测试我提供的伪代码。

It also helps to understand how Java creates an anonymous inner class. How Java implements that particular class.

Java needs for that variable to be final because the compiler must know the type of that object at compile time. The compiler will then generate a field within the anonymous inner class implementation (in this case 'et').

If the type is not final, how would the compiler determine how to build the inner class implementation. Basically, by declaring the field final, you are giving the Java compiler more information.

Code that doesn't help the compiler, won't compile your anonymous inner class:

Object et;
et = a ? new Object() : new EditText();

...

With the code above, the Java compiler cannot really build the anonymous inner class.

Your code:

final EditText et=(EditText)findViewById(R.id.t);

...

new Button.OnClickListener$1(){
            public void onClick(View v)<br>
            {
            Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText()));
            startActivity(on);
            }
        });

...
The java compiler will create a bytecode class, an implementation of that inner class block that you provided that might look like this.

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);
                }
}

You can test the pseudo code I provided by finding the anonymous bytecode class $1 and decompile that bytecode file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文