java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类。内部类又分为:常规内部类、局部内部类、匿名内部类和静态嵌套类四种。我们内部类的知识在Android手机开发中经常用到。

一、常规内部类

所谓常规内部类,或者说内部类,指的就是除去后面三种之外的内部类(这算什么解释。。。)

先写一个最简单的内部类的例子,大家感觉一下:

view sourceprint?1 public class Outer {

2     public class Inner{

3     }

4 }

编译一下,我们看到目录中出现了两个class文件,其中有一个文件名叫做Outer$Inner.class,带了一个$符号,这个特点让我们很容易的认出来这是内部类编译后的class文件。

再写一个稍微复杂一点的内部类:

view sourceprint?01 public class Outer {

02

03     private int x=1;

04

05     public Outer(){

06         System.out.println("Outer initial");

07     }

08

09     public class Inner{

10

11         public Inner(){

12             System.out.println("Inner initial");

13         }

14

15         private int x=2;

16

17         public  void add(){

18             int x=3;

19             System.out.println(x);

20             System.out.println(this.x);

21             System.out.println(Outer.this.x);

22         }

23

24     }

25

26     public static void main(String[] args){

27         Inner inner = new Outer().new Inner();

28         inner.add();

29     }

30 }

我们编译以后,运行一下看看:

在上面的例子里我们可以清晰的看到:

内部类就像一个实例成员一样存在于外部类中。

内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制。

内部类中的this指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名.this的方式获得。

内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员。

下面我们再小结一下内部类的创建方法:

在外部类的内部,可以用 Inner inner = new Inner(); 方法直接创建

在外部类外部,必须先创建外部类实例,然后再创建内部类实例,除了上面 Inner inner = new Outer().new Inner()的写法以外,还有 Outer outer = new Outer(); Inner inner = outer.new Inner();的写法

二、局部内部类

我们也可以把类定义在方法内部,这时候我们称这个类叫局部内部类。

我们再看一个例子:

view sourceprint?01 public class Outer {

02

03     int x =1;

04     public void doSomething(){

05         final int y=2;

06         class Inner{

07             int x =3;

08             void print(){

09                 int x=4;

10                 System.out.println(x);

11                 System.out.println(this.x);

12                 System.out.println(Outer.this.x);

13                 System.out.println(y);

14             }

15         }

16         Inner inner = new Inner();

17         inner.print();

18     }

19

20     public static void main(String[] args){

21         Outer outer = new Outer();

22         outer.doSomething();

23     }

24 }

运行程序,查看结果:

我们通过上面这里例子也可以看到下面几点:

局部内部类的地位和方法内的局部变量的位置类似,因此不能修饰局部变量的修饰符也不能修饰局部内部类,譬如public、private、protected、static、transient等

局部内部类只能在声明的方法内是可见的,因此定义局部内部类之后,想用的话就要在方法内直接实例化,记住这里顺序不能反了,一定是要先声明后使用,否则编译器会说找不到。

局部内部类不能访问定义它的方法内的局部变量,除非这个变量被定义为final 。

是不是有点不好理解?关于为什么用final修饰以后就可以用了,我打算专门在番外篇里专门写一篇博客给你讲清楚,先记住吧。

三、匿名内部类

当我们把内部类的定义和声明写到一起时,就不用给这个类起个类名而是直接使用了,这种形式的内部类根本就没有类名,因此我们叫它匿名内部类。

我们再看一个有趣的例子:

view sourceprint?01 public class Dog {

02

03     public interface Pet {

04

05         public void beFriendly();

06         public void play();

07

08     }

09

10     public static void main(String[] args){

11

12         Pet dog = new Pet(){

13             @Override

14             public void beFriendly() {

15                 System.out.println("蹭蹭你^_^");

16             }

17             @Override

18             public void play() {

19                 System.out.println("把飞盘叼给你,逼你把飞盘丢出去,然后它再捡回来让你继续扔,连续500次^_^");

20             }

21         };

22

23         dog.beFriendly();

24         dog.play();

25

26     }

27 }

编译和运行程序,查看结果:

竟然编译和运行都很正常,我们知道抽象类和接口肯定无法实例化的,因此刚才的例子肯定有点意思:

第一匿名内部类可以是个接口,这个没什么好奇怪的哈。

第12行到第21行是一个语句,就是定义了一个对象,因此21行大括号后面有个分号。

匿名内部类用 new Pet(){ … } 的方式把声明类的过程和创建类的实例的过程合二为一。

匿名内部类可以是某个类的继承子类也可以是某个接口的实现类。

好吧我们再看一个例子,方法参数内的匿名内部类:

view sourceprint?01 public class Dog {

02

03     static abstract class Ball {

04         abstract String getName();

05     }

06

07     void play(Ball b){

08         System.out.println(b.getName());

09     }

10

11     public static void main(String[] args){

12         Dog dog = new Dog();

13

14         dog.play(new Ball(){

15             @Override

16             String getName() {

17                 return "qiu qiu";

18             }});

19     }

20 }

编译和运行以后的截图我就不给你了,返回值就是“qiu qiu”。

从第14行到第18行是一句话,就是执行一个play方法,而这个方法的参数就由一个匿名内部类的实例来提供。

四、静态嵌套类

为了让你感觉舒服一些,我们也把最简单的内部类放在最后讲。

当一个内部类前面用static修饰时,我们称之为静态嵌套类或者说静态内部类。

上面的例子里其实我们已经看到过静态嵌套类了,下面我们再举一个例子:

view sourceprint?01 public class Outer {

02

03     static int x =1;

04

05     static class Nest {

06

07         void print(){

08             System.out.println("Nest "+x);

09         }

10     }

11

12     public static void main(String[] args){

13         Outer.Nest nest = new Outer.Nest();

14         nest.print();

15     }

16 }

因为静态嵌套类和其他静态方法一样只能访问其它静态的成员,而不能访问实例成员。因此静态嵌套类和外部类(封装类)之间的联系就很少了,他们之间可能也就是命名空间上的一些关联。上面例子中你需要注意的就是静态嵌套类的声明方法 new Outer.Nest() 连续写了两个类名,以至于我们都怀疑前面的Outer是个包名了,好在包名一般都小写的,要不还真分不清……

再强调一遍,内部类在Android中应用的非常多,理解和使用好显得蛮重要。

匿名类不等同于匿名内部类

匿名类不等同于匿名内部类,后者也经常使用,匿名内部类是内部类的一种,使用的时候更加简洁,但是不是任何情况下都需要使用。

在thinking in java 3th 是这么阐述的:

简单地说:匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较

合适的:

  ·只用到类的一个实例。
  ·类在定义后马上用到。
  ·类非常小(SUN推荐是在4行代码以下)
  ·给类命名并不会导致你的代码更容易被理解。
  在使用匿名内部类时,要记住以下几个原则:

  ·匿名内部类不能有构造方法。
  ·匿名内部类不能定义任何静态成员、方法和类。
  ·匿名内部类不能是public,protected,private,static。
  ·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
  ·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

学习Android之内部类的更多相关文章

  1. java学习面向对象之内部类

    什么是面向对象内部类呢?所谓的内部类,即从字面意义上来理解的话,就是把类放到类当中. 那么内部类都有什么特点呢? 1.内部类可以访问包裹他的类的成员. 2.如果包裹他的类想访问被其包裹的类的话就得实例 ...

  2. JavaSE 学习笔记之内部类(九)

    内部类:如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象.这时,为了方便设计和访问,直接将A类定义在B类中.就可以了.A类就称为内部类.内部类可以直接访问外部类中的成员.而外部类想要访问内 ...

  3. 学习android学习必备的java基础知识--四大内部类

    学习android必备的java基础知识--四大内部类 今天学习android课程,因为我的主专业是JAVA,但是兴趣班却有这其他专业的同学,学习android 需要具备一些java的基础知识,因此就 ...

  4. 想学习Android开发

    最近被别人说知识面窄,心里受伤了.准备学学Android开发,如果能在手机里运行自己写的app,那是多么high ~~~ Android开发需要看什么资料呢? 说明:本人一直从事windows下的C+ ...

  5. 从零开始学习Android(一)Android环境的搭建

    好久没有开始写博客了,最近开始学习Android,所以想把学习的笔记都一一记录下来.一来是方便自己以后资料的查询,其次也是给Android新手朋友进行学习使用,再次也希 望得到高手的指点.废话少说,我 ...

  6. 《IT蓝豹》吹雪花demo,学习android传感器

    吹雪花demo,学习android传感器 吹雪花demo,学习android传感器,嘴巴对着手机底部吹一下就会出现飘着雪花效果. 算是学习android传感器效果.本例子主要是通过android.me ...

  7. 一起来学习Android自定义控件1

    概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...

  8. 10个很棒的学习Android 开发的网站(转)

    看到江湖旅人 写的<10个很棒的学习iOS开发的网站 - 简书>,所以就忍不住写Android 啦,也希望对大家有帮助.我推荐的网站,都是我在学习Android 开发过程中发现的好网站,给 ...

  9. 深入学习Android有关网络连接的内容

    基于实际项目中碰到的些许问题,开始重新深入学习Android网络连接有关知识. Android的4.1.2版本的AndroidHttpClient模块setSoTimeout之后实际超时时间和设置的时 ...

随机推荐

  1. 解决Ajax跨域问题:Origin xx is not allowed by Access-Control-Allow-Origin.

    一:使用jsonp格式, 如jquery中ajax请求参数   dataType:'JSONP'. <html> <head> <title>title</t ...

  2. UTF8后MD5

    function ToUTF8Encode(str: string): string; //将字符串转UTF8编码 var b: Byte; begin for b in BytesOf(UTF8En ...

  3. SDP协议分析

    一.SDP协议介绍 SDP 完全是一种会话描述格式 ― 它不属于传输协议 ― 它只使用不同的适当的传输协议,包括会话通知协议(SAP).会话初始协议(SIP).实时流协议(RTSP).MIME 扩展协 ...

  4. Spark Streaming揭秘 Day27 Job产生机制

    Spark Streaming揭秘 Day27 Job产生机制 今天主要讨论一个问题,就是除了DStream action以外,还有什么地方可以产生Job,这会有助于了解Spark Streaming ...

  5. Spark Streaming揭秘 Day20 动态Batch size实现初探(上)

    Spark Streaming揭秘 Day20 动态Batch size实现初探(上) 今天开始,主要是通过对动态Batch size调整的论文的解析,来进一步了解SparkStreaming的处理机 ...

  6. shell curl

    最近突然发现了一个有趣的问题:怎样判断日期是工作日还是节假日.(http://www.cnblogs.com/ZXdeveloper/p/4018886.html) 顺便发现了一个有用的网址:http ...

  7. Sharing

    To store English words, one method is to use linked lists and store a word letter by letter. To save ...

  8. android include中的控件调用

    项目中经常会有一些布局是重用的,但是如何来更好的利用这些布局中的控件 转: http://zhidao.baidu.com/link?url=GU93U8Wu31dfp7mKEx52hMJkxjFLC ...

  9. OO之装饰者模式

    以下为装饰者模式详解: 引子: 假如有一个快餐店,基本种类分为米饭,水饺,粉面等,但每一种类型的快餐又可以搭配不同的料,如米饭可以点各种不同的菜(排骨,青菜,土豆等),如果按照一般的设计,快餐为基类, ...

  10. 分布式日志收集系统--Chukwa

    1. 安装部署 1.1 环境要求 1.使用的JDK的版本必须是1.6或者更高版本,本实例中使用的是JDK1.6 2.使用的hadoop的版本必须是Hadoop0.20.205.1及以上版本,本实例中使 ...