在Android项目中,我使用下面的代码。我收到错误:variable tts might not have been initialized
。如果我改变变量tts被声明的地方,我不会再出错。如果我注释掉在内部OnInitListener类中引用tts的两行,我也不会再发生错误(但也没有任何有趣的事情发生)。因此,我推论,如果内部类在封闭方法中声明(即使它被声明为final
),也不能“看到”tts
变量,但是当它被声明为实例变量时它可以看到它封闭类。了解Java内部类中的范围
我来自JavaScript背景;显然Java在这种情况下以不同的方式处理变量作用域。如果你能解释Java在底层做什么,我将不胜感激,以便我能理解这些差异。
package com.example.texttospeech;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import java.util.HashMap;
import java.util.Locale;
public class MainActivity extends ActionBarActivity {
//private TextToSpeech tts; // UNCOMMENT THIS...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testTextToSpeech();
}
private void testTextToSpeech() {
final String toSpeak = getString(R.string.hello_world);
final int mode = TextToSpeech.QUEUE_FLUSH;
final HashMap hashMap = new HashMap<String, String>();
final TextToSpeech tts; // ... AND COMMENT THIS OUT...
tts = new TextToSpeech(getApplicationContext(),
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
// ... OR SIMPLY COMMENT OUT THE NEXT TWO LINES
tts.setLanguage(Locale.UK);
tts.speak(toSpeak, mode, hashMap);
}
}
});
}
}
我在哪里可以了解隐式字段的创建时间和时间? #2似乎创造了一种鸡与鸡蛋的情况,其中''侦听器'不能被创建,直到'tts'被初始化。至于#3,我可以看到内部类在外部类中声明为'private TextToSpeech tts;'时可以从外部类访问变量。 – 2014-11-08 21:09:09
老实说,我在这里学到了关于stackoverflow的阅读问题和答案:)没有什么可以学习的,它只是内部类对outter类的引用,以及它声明的方法中的所有最终字段。随着内部阶层的生活,这些其他对象不能由GC收集。 – NameSpace 2014-11-08 21:28:20
我是否正确地认为您的可行方法与我在示例代码中提到的“取消注释/注释掉”更改相同?在我看来,这个问题来自这样一个事实,即如果在'testTextToSpeech()'中声明'java'编译器坚持'tts'被设置为'final'。即使我使用'final TextToSpeech tts = new TextToSpeech(...);'编译器仍然不满意。在调用'onInit()'方法时,'tts'将指向一个已初始化的对象,但编译器无法看到它。它看到的只是'最后'。这是一个准确的理解? – 2014-11-08 21:37:09