`
仅此而已
  • 浏览: 62205 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

内部类理解【转】

 
阅读更多

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

一、常规内部类

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

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

1 public class Outer {
2     public class Inner{
3     }
4 }

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

K6DP_~XUH}@$_Y$ZEYMFE@T

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

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 }

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

 image

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

  1. 内部类就像一个实例成员一样存在于外部类中。
  2. 内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制。
  3. 内部类中的this指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名.this的方式获得。
  4. 内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员。

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

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

 

二、局部内部类

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

我们再看一个例子:

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 }

运行程序,查看结果:

image

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

  1. 局部内部类的地位和方法内的局部变量的位置类似,因此不能修饰局部变量的修饰符也不能修饰局部内部类,譬如public、private、protected、static、transient等
  2. 局部内部类只能在声明的方法内是可见的,因此定义局部内部类之后,想用的话就要在方法内直接实例化,记住这里顺序不能反了,一定是要先声明后使用,否则编译器会说找不到。
  3. 局部内部类不能访问定义它的方法内的局部变量,除非这个变量被定义为final 。

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

三、匿名内部类

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

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

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 }

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

image

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

  1. 第一匿名内部类可以是个接口,这个没什么好奇怪的哈。
  2. 第12行到第21行是一个语句,就是定义了一个对象,因此21行大括号后面有个分号。
  3. 匿名内部类用 new Pet(){ … } 的方式把声明类的过程和创建类的实例的过程合二为一。
  4. 匿名内部类可以是某个类的继承子类也可以是某个接口的实现类。

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

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修饰时,我们称之为静态嵌套类或者说静态内部类。

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

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中应用的非常多,理解和使用好显得蛮重要。

分享到:
评论

相关推荐

    java 匿名内部类的使用规范

    本篇文章将深入探讨Java匿名内部类的使用规范,帮助你更好地理解和应用这一特性。 首先,理解匿名内部类的基本概念。匿名内部类没有名字,它不能被其他类直接引用,但可以作为局部变量、成员变量或者方法参数。它...

    内部类知识总结3--匿名内部类

    通过阅读源码,我们可以更好地理解和学习匿名内部类的实际应用。 9. **工具支持** 开发工具如IDEA或Eclipse对匿名内部类提供了很好的支持,包括自动完成、重构和代码提示等功能,使开发过程更加高效。 总之,匿名...

    内部类的使用

    内部类可以轻松地访问外部类的成员,使得代码结构清晰且易于理解。 接下来,让我们转向Stream API。Java 8引入了Stream API,为集合操作提供了函数式编程风格。Stream可以理解为数据处理的管道,它允许我们对集合...

    java和kotlin的内部类静态嵌套类

    总的来说,理解Java和Kotlin的内部类和静态嵌套类是成为一名合格的移动开发者的基础。通过学习和实践,你可以更好地组织代码,提高代码质量,同时降低维护成本。在提供的资源中,"java内部类嵌套类"和"kotlin内部类...

    控制器(内部类)

    首先,让我们理解什么是内部类。内部类分为四种类型:成员内部类、局部内部类、匿名内部类和静态内部类。控制器通常会用到的是成员内部类或静态内部类,因为它们可以访问外部类的属性和方法,同时又具有一定的封装性...

    反射私有内部类的例子

    ### 反射私有内部类的例子 #### 一、引言 在Java编程语言中,反射(Reflection)是一项强大的功能,允许程序在运行时检查和修改自身结构与行为。通过反射,可以动态地获取类的信息并操作其字段、方法以及构造器等。...

    JAVA内部类

    ### JAVA内部类详解 ...理解每种内部类的特点及其适用场景,将有助于开发者更高效地设计和实现软件系统。在实践中,合理利用内部类的优势,可以提升代码的清晰度和可读性,同时保持良好的性能和可维护性。

    Hadoop源代码分析(Task的内部类和辅助类)

    本文将深入剖析`Task`类中的内部类及其辅助类,旨在理解这些类如何协同工作以支持MapReduce任务的正常运行。 #### MapOutputFile管理Mapper的输出文件 `MapOutputFile`是管理`Mapper`输出文件的重要组件,它提供了...

    java(Day12)---内部类

    Java中的内部类是一种特殊的类,它可以被定义在一个外部类的内部。这种设计允许内部类访问外部类的所有成员,包括私有成员,增强了代码的封装性和灵活...理解并熟练运用这些类和内部类机制对于Java开发者来说至关重要。

    java学习资料抽象类,接口,内部类

    在这个Java学习资料中,我们重点探讨抽象类、接口和内部类。 首先,抽象类是一种不能实例化的类,它主要用于被其他类继承。在Java中,使用`abstract`关键字来定义一个抽象类。抽象类可以包含抽象方法(无方法体的...

    MapReduce,泛型,匿名内部类,Runnable和Callable

    总结来说,MapReduce是大数据处理的关键技术,泛型提供了强大的类型安全和代码复用,匿名内部类简化了多线程编程,而`Runnable`和`Callable`则是Java多线程编程的基础。了解和掌握这些概念对于理解现代分布式系统和...

    使用适配器类(匿名内部类).rar_适配器

    适配器模式是一种软件设计模式,它允许不兼容的接口之间进行通信,使得原本由于接口不匹配而不能一起工作的类可以协同工作...通过阅读“使用适配器类(匿名内部类)”的源代码,你可以更深入地理解这一模式的实现细节。

    day05_内部类和Lambda表达式.zip

    在Java编程语言中,内部类和Lambda表达式是两种非常重要的高级特性,它们极大地提高了代码的简洁性和...在学习"day05_内部类和Lambda表达式"这个主题时,你将深入理解它们的工作原理,并能够在实际项目中灵活应用。

    day03-内部类&API1

    【标题】:“内部类&API1”的讲解 【描述】:本内容主要涵盖了类名、抽象类和接口作为参数及返回值的使用,以及内部类的基础应用。 【知识点详解】: 1. 参数传递: - **类名作为形参和返回值**:在Java中,当...

    把wsdl文件转换成java类 使用wsdl2Java工具

    4. **理解生成的代码**: 生成的Java类包括: - **Service Interface**: 这是Web服务的接口,定义了服务提供的方法。 - **Port Type Classes**: 这些类代表了WSDL中的portType元素,包含了服务的操作方法。 - **...

    Java软件开发实战 Java基础与案例开发详解 8-1 内部类与包装器 共15页.pdf

    ### Java软件开发实战:内部类与包装器 #### 8-1 内部类与包装器 ##### 内部类概述 ...以上内容涵盖了Java内部类和包装器的基础概念及其具体应用,希望能够帮助您更好地理解和掌握这些重要的Java概念。

    内部类及lambda表达式的日常练习

    通过对这些文件的分析,我们可以深入理解内部类和Lambda的实际应用,比如它们如何与集合操作、多线程、函数式接口等核心概念结合。 总结来说,这个练习涵盖了Java中两个重要的高级特性:匿名内部类和Lambda表达式。...

    【IT十八掌徐培成】Java基础第06天-05.匿名内部类-适配器模式.zip

    本讲义将深入探讨Java中的匿名内部类与适配器模式,这两种概念在实际开发中都有着广泛的用途。 首先,让我们了解一下匿名内部类。匿名内部类,顾名思义,就是没有名字的类,它可以在需要使用类的地方直接定义,无需...

    举例讲解Java的内部类与类的加载器

    理解内部类和类加载器的概念对于深入学习Java以及进行JVM相关的优化至关重要。它们在实际开发中也有广泛的应用,例如,自定义类加载器可以用于动态加载或替换类,内部类常用于事件处理、线程同步等场景。

    汉字转拼音类.rar

    这个汉字转拼音类很可能包含了内部字库,用于存储汉字与拼音的映射关系。这种字库可能以哈希表或其他高效的数据结构实现,以便快速查找每个汉字的拼音。此外,类可能还包含了错误处理机制,以应对无法转换的汉字或...

Global site tag (gtag.js) - Google Analytics