匿名内部类请求澄清

3
在学习Android上的TTS时,我遇到了以下的代码片段:
    speakBtn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            mTts.speak(words.getText().toString(), TextToSpeech.QUEUE_ADD, null);
        }});

我对Java还很陌生,所以我的识别各种结构的信心并不太高。我认为上面看到的是匿名内部类,但“new OnClickListener()”让我感到困惑。请确认和/或更正以下理解:

  1. 内部类定义在new OnClickListener()之后。
  2. OnClickListener是内部类派生的超类。
  3. (匿名)内部类只有一个成员函数:OnClick()。
  4. @Override在内部类定义中是什么意思?如果这是一个注释,那么我有点困惑,因为此答案表明不能注释匿名内部类。

最后,有没有一种更容易理解的方法来编写上面的片段呢?

5个回答

5
  1. 是的,它在大括号之间定义。
  2. 是的,只是它是一个接口,而不是类。
  3. 是的。
  4. 您无法添加类级别的注释。
    @Override 是一个方法级别的注释,可以正常工作。

3

基本上,这段代码创建了一个类,编译器为您方便起见使用了混淆名称,因此您不需要自己命名。该类将实现接口OnClickListener,并包含onClick(View)方法的实现,因为接口要求。

因此,您的片段可以像这样编写:

class OnClickListenerThingy01 implements OnClickListener { // name is invented from the top of my head and corresponds actual name manging in no way
    @Override
    public void onClick(View view) {
        mTts.speak(words.getText().toString(), TextToSpeech.QUEUE_ADD, null);
    }
}
speakBtn.setOnClickListener(new OnClickListenerThingy01());

@Override注解不是放在类本身上的 - 在你的代码中没有声明,注解可以被添加,由编译器生成 - 而是放在方法上。
@Override注解用于标记覆盖和方法实现。其主要作用是在重写的方法签名发生变化时生成编译器错误,但您未更新相应的覆盖声明,以便当您的覆盖失效时,您不会感到惊讶,因为例如被覆盖的内容更改了名称。
在接口实现的情况下,如果您忘记完全实现接口,则编译器将生成一个错误,因此@Override可能看起来有点冗余,但实际上并非如此。事实上,这是一个相当好的东西,可以避免在您的代码中保留不必要的方法(例如,从接口中删除方法声明时)。
尽管必须注意的是像Eclipse这样的IDE很可能使这些问题无效,因为提供的重构工具足以避免这种情况。不管怎样,在可能使用时,@Override是一个非常不错的方法。

2

这里有一种重写代码片段的方法,可以让它更容易被“新手”理解 :)

class MyOuterClass {
    private class MyOnClickListener implements OnClickListener {
        @Override
        public void onClick(View view) {
            mTts.speak(words.getText().toString(), TextToSpeech.QUEUE_ADD, null);
        }
    }

    // later (inside some method)...
        speakBtn.setOnClickListener(new MyOnClickListener());
}

1
  • 内部类是在new OnClickListener()之后定义的。

把那段代码看作是OnClickListener()的一个未命名子类。类定义在括号里,就像你想的那样。

  • OnClickListener是内部类派生的超类。

是的。

  • (匿名)内部类只有一个成员函数:OnClick()。

确实如此,但这不一定是唯一的情况。它可以有更多的成员函数。

  • 在内部类的定义中,@Override是什么?如果这是一个注释,那我很困惑,因为这个答案说匿名内部类不能被注释。

@Override用于方法的编译时错误检查。你可以在匿名内部类上使用方法级别的注释。


0
OnClickListener是一个超类,内部类是由它派生的。
实际上并不是这样:OnClickListener不是一个类。这种语法用于创建一个实现OnClickListener接口的新(匿名)类的实例。因此,您只需要实现一个方法:onClick()。

接口不就是一个(虚拟抽象)类吗? - an00b
是的,你说得对。接口是完全抽象的类。但为了避免混淆,我们不将接口视为类 ;) - Romain Guidoux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接