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. memcache的一致性hash算法

    <?php /** * 一致性哈希memcache分布式,采用的是虚拟节点的方式解决分布均匀性问题,查找节点采用二分法快速查找 * the last known user to change t ...

  2. jquery 获取 CheckBox 的状态

    <td style="width:220px;vertical-align:central;"><input type="checkbox" ...

  3. Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解

    Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解 今天主要理一下StreamingContext的启动过程,其中最为重要的就是Jo ...

  4. 关于hadoop2.4.2版本学习时遇到的问题

    问题一:namenode启动失败 描述:在初始化后hadoop后,发现datanode启动失败,namenode则可以正常启动,如果把用户换成root权限,再次启动时,则namenode和datano ...

  5. ENVI中利用polygon掩膜修改类到指定类

    overlay——classification——制定分类的图像 edit——polygon delete from class(选择这个掩膜模式) edit——set delete class va ...

  6. 用JS给浏览器的关闭按钮添加事件

    以下是指在js中实现,而非 <body onunload="close()"> 这种方法! 因为这样是在unload掉body的时候触发,而无论任何浏览器,都会在关闭的 ...

  7. 【学习总结】【多线程】 线程 & 进程 & NSThread(多线程的一套API)

    一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开 Chrome.Xcode,系统就会分别启动2个进 ...

  8. 【BZOJ 1295】 [SCOI2009]最长距离

    Description windy有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格 ...

  9. oc 中四种实例变量的范围类型@private@protected@public@package

    To enforce the ability of an object to hide its data, the compiler limits the scope of instance vari ...

  10. C++中头文件相互包含与前置声明

    一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题.假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中, ...