一、前期基础知识储备——Android开发中常见的与内部类相关的操作:
以button点击事件的实现为例—Android中实现button点击事件的监听方法有很多种,这里总结了常用的四种方法:
(1)匿名类
(2)匿名内部类,与(1)类似,更为常用
(3)内部类中实现OnClickListener接口
(4)主类中实现OnClickListener接口
上代码,实现上述四种方法:
(1)使用匿名类实现button点击事件:
button.setOnClickListener(listener );
private View.OnClickListener listener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
String phonenum = phoneEditText.getText().toString();
Intent intent = new Intent("android.intent.action.CALL", Uri.parse("tel:" + phonenum));
startActivity(intent);
}
};(2)使用匿名内部类实现button点击事件,最常用;
Button button1=(Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.i("定义属性响应按钮点击事件");
}
});//当按钮较少或只有一个按钮时,可以直接创建OnClickListener的匿名内部类传入按钮的setOnClickListener参数中(3)内部类中实现OnClickListener接口实现button点击事件;
button.setOnClickListener(new ButtonListener());
private final class ButtonListener implements View.OnClickListener{
public void onClick(View v)
{
......
}
}(4)主类中实现OnClickListener接口实现button点击事件;
public class MainActivity extends Activity implements onClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1=(Button) findViewById(R.id.button1);
//按钮绑定接口
button1.setOnClickListener(this);
}
//在重载的方法中实现点击设置
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:
Log.i("定义属性响应按钮点击事件");
break;
}
}
}
小结:1、在实现监听的时候都是需要两步走;
①绑定button按钮
②监听button事件
2、具体使用什么方法去实现button按钮点击事件的监听要看具体的需求,都各有各的好处和不足。如果只使用一次则推荐使用匿名内部类的方法。
3、Android开发中有很多按钮,但是监听的方法常用的都是这几种,所以能够举一反三,这也是为什么写这个的原因,比如笔者之前写过的ToggleButton。
二、Java内部类详解
(1)为什么使用内部类:因为Java是单继承的,依靠实现接口并不能真的实现多继承,如何结合接口和内部类就可以真正实现多继承。比如,你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法名称参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能。
(2)Java中内部类的分类:
①成员内部类;②局部内部类;③匿名内部类;④静态内部类
注:匿名内部类是一种特殊的局部内部类
(3)上代码,具体实现:
①成员内部类,即作为外部类的一个成员存在,与外部类的属性、方法并列。注意:成员内部类中不能定义静态变量,但可以访问外部类的所有成员。
public class Outer{
private static int outer_i = 1;
private int k=20;
public static void outer1(){
}
class Inner{
int j=100;
int inner_i=1;
void inner1(){
System.out.println(outer_i);
System.out.println(k);
outer1();
}
}
public void outer2(){
Inner inner = new Inner();
inner.inner1();
} ②局部内部类,即在方法中定义的内部类,与局部变量类似,在局部内部类前不加修饰符public或private,其范围为定义它的代码块。
public class Outer {
public void say(){
System.out.println("关门说真话!");
}
}
public class Test {
public void ting(){
class MiMi extends Outer{//定义一个局部的内部类,继承Outer方法
}
new MiMi().say();//调用局部内部类中继承的say方法
System.out.println("别人都不知道");
}
③匿名内部类,匿名内部类是在抽象类和接口的基础之上发展起来的。匿名内部类如果继承自接口,必须实现指定接口的方法,且无参数。匿名内部类如果继承自类,参数必须按父类的构造函数的参数传递。
abstract class parent {
public abstract void like();
}
public class Demo {
public static void main(String[] args) {
parent pt = new parent(){
public void like(){
System.out.println("吃饭睡觉打豆豆。。。");
}
};
pt.like();
}
}④静态内部类,静态内部类定义在类中,任何方法外,用static定义。
public class StaticTest {
private static String name="abc";
private String sex="男";
static class Person{
private String age = "18";//内部私有成员
public String heigth = "180";//内部类公有成员
public void display(){
//System.out.println(sex);//报错,不能直接访问外部类的非静态成员
System.out.println(name);//只能直接访问外部类的静态成员
System.out.println(age);//访问本内部类成员。
}
}
小结:1、内部类作为外部类的一个特殊的成员来看待,因此它有类成员的封闭等级:private ,protected,默认(friendly),public 它有类成员的修饰符: static,final,abstract。
2、非静态内部类nested inner class,内部类隐含有一个外部类的指针this,因此,它可以访问外部类的一切资源(当然包括private)外部类访问内部类的成员,先要取得内部类的对象,并且取决于内部类成员的封装等级。非静态内部类不能包含任何static成员。
3、静态内部类:static inner class,不再包含外部类的this指针,并且在外部类装载时初始化. 静态内部类只能访问外部类static成员. 外部类访问静态内部类的成员:static成员:类名.成员;非static成员:对象.成员
4、对于方法中的内部类或块中内部类只能访问块中或方法中的final变量。
三、匿名内部类再分析
为什么要再分析,因为Android开发中比较典型的内部类使用,就是匿名内部类,所以必须要掌握,这也是为什么本篇文章的前期知识储备部分放的是Android中button点击事件的实现,因为这里的button点击事件的内部类实现方式很有代表性,而且也很常用。
先看段伪代码
abstract class Father(){
....
}
public class Test{
Father f1 = new Father(){ .... }; //这里就是有个匿名内部类
}
一般来说,new 一个对象时小括号后应该是分号,也就是new出对象该语句就结束了。但是出现匿名内部类就不一样,小括号后跟的是大括号,大括号中是该new 出对象的具体的实现方法。因为我们知道,一个抽象类是不能直接new 的,必须先有实现类了我们才能new出它的实现类。上面的伪代码就是表示new 的是Father的实现类,这个实现类是个匿名内部类。其实拆分上面的匿名内部类可为:
class SonOne extends Father{
...//这里的代码和上面匿名内部类,大括号中的代码是一样的
}
public class Test{
Father f1 = new SonOne() ;
}
在thinking in java 3th 是这么阐述内部类的:简单地说:匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的,这里只记住一个:
·只用到类的一个实例。
在使用匿名内部类时,要记住最重要的一个原则:
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。