我是java编程的初学者,我目前正在研究libGDX的编程。在书中用libGDX开始Java游戏开发"有关如何制作一些基本游戏的说明。其中之一(游戏是处理鼠标和触摸输入的介绍)我们制作了一个游戏,其中气球在屏幕的左侧产生,这些气球继续向右侧移动,并且每个气球都从游戏中移除当你点击它,或当它离开屏幕时(当X大于屏幕的宽度时)
我在此代码中理解final
的使用时遇到问题:
spawnTimer += delta;
// check time for next balloon spawn
if(spawnTimer > spawnInterval)
{
spawnTimer -= spawnInterval;
final Balloon b = new Balloon();
b.addListener
(
new InputListener()
{
public boolean touchDown (InputEvent event, float x, float y, int pointer, int buttoon)
{
popped++;
b.remove();
return true;
}
}
);
mainStage.addActor(b);
}
if statement
内的代码负责创建名为Balloon
的actor的实例,并向其添加Input Listener
,因此它将执行此代码:
popped++;
b.remove();
return true;
触摸时在本书中final
并未用于创建Balloon
的新实例,我只使用它,因为Android Studio让我这样做(它说我无法使用{{ 1}}因为它是一个将在实例中使用的代码或类似的东西),它似乎有效。我想知道为什么使用b.remove()
有效。
当方法(update())完成它的事情时,final
对象是否被处理掉了(这就是为什么它会赢得错误然后再次使用该行)?< / p>
执行final
时,它将如何知道要删除的内容?
当我创建一个这样的实例时,我认为它给它起了一个名字,但它只是创建一个实例和一个指针,对吧?
所以,如果我放松了我刚刚创建的指针,我只能从实例内部(或者可能来自b.remove()
)获得另一个指针?
答案 0 :(得分:-1)
所以,当你打电话给new InputListener() {
时......你可能已经明白你正在创建一个匿名的内部类。使用匿名内部类的一个主要好处是可以在类成员(例如方法)中声明它,因此内部类可以访问封闭成员的元素,例如变量{{1 }}。您已捕获了封闭方法变量的值。在其他语言中,这通常被称为“封闭”。如果检查生成的字节码,您将看到新的内部类将具有类型为Balloon b
的字段和类型为Balloon
的构造函数参数。使用构造函数,变量Balloon
将被复制到内部类的字段中。
在Java之前,有许多编程语言允许您以这种方式捕获值,但是其中许多语言在代码中引起了难以看到的问题,因为这些变量通常可以在方法中自由更改。调用b
后,内部类的touchDown
方法可能不会立即执行。如果该封闭方法中的代码在执行b.addListener
之前为b
分配了不同的对象,该怎么办?执行时应使用哪个touchDown
的引用?原来的还是新的?
Java解决此问题的方法是坚持内部类捕获的任何方法变量都是final,这样可以确保以后在方法中不会更改它。如果您尝试捕获非final的变量,编译器将失败并显示错误。
作为旁注,Java 8样式的lambda表达式在内部编译为内部类,但实际上它们捕获变量的规则略有不同,但结果是相同的。而不是坚持捕获的任何变量是明确最终的,而是静态分析封闭方法以确保没有代码分配给该变量。如果是这样,您将收到一个错误,即该变量必须“有效”。最终