`

匿名类与内部类

阅读更多

(来自:http://jnotnull.iteye.com/blog/231333

 

提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比。内部类从表面上看,就是在类中又定义了一个类(下文会看到,内部类可以在很多地方定义),而实际上并没有那么简单,乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了解,你会发现Java的设计者在内部类身上的确是用心良苦。学会使用内部类,是掌握Java高级编程的一部分,它可以让你更优雅地设计你的程序结构。下面从以下几个方面来介绍: 

第一次见面

Java代码 
  1. public interface Contents {   
  2. int value();   
  3. }   
  4.   
  5. public interface Destination {   
  6. String readLabel();   
  7. }   
  8.   
  9. public class Goods {   
  10. private class Content implements Contents {   
  11. private int i = 11;   
  12. public int value() {   
  13. return i;   
  14. }   
  15. }   
  16.   
  17. protected class GDestination implements Destination {   
  18. private String label;   
  19. private GDestination(String whereTo) {   
  20. label = whereTo;   
  21. }   
  22. public String readLabel() {   
  23. return label;   
  24. }   
  25. }   
  26.   
  27. public Destination dest(String s) {   
  28. return new GDestination(s);   
  29. }   
  30. public Contents cont() {   
  31. return new Content();   
  32. }   
  33. }   
  34.   
  35. class TestGoods {   
  36. public static void main(String[] args) {   
  37. Goods p = new Goods();   
  38. Contents c = p.cont();   
  39. Destination d = p.dest("Beijing");   
  40. }   
  41. }   
在这个例子里类Content和GDestination被定义在了类Goods内部,并且分别有着protected和private修饰符来控制访问级别。Content代表着Goods的内容,而GDestination代表着Goods的目的地。它们分别实现了两个接口Content和Destination。在后面的main方法里,直接用 Contents c和Destination d进行操作,你甚至连这两个内部类的名字都没有看见!这样,内部类的第一个好处就体现出来了——隐藏你不想让别人知道的操作,也即封装性。 
同时,我们也发现了在外部类作用范围之外得到内部类对象的第一个方法,那就是利用其外部类的方法创建并返回。上例中的cont()和dest()方法就是这么做的。那么还有没有别的方法呢?当然有,其语法格式如下: 

Java代码 
  1. outerObject=new outerClass(Constructor Parameters);   
  2.   
  3. outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);   



注意在创建非静态内部类对象时,一定要先创建起相应的外部类对象。至于原因,也就引出了我们下一个话题—— 

非静态内部类对象有着指向其外部类对象的引用 
对刚才的例子稍作修改: 

Java代码 
  1. public class Goods {   
  2.   
  3. private valueRate=2;   
  4.   
  5. private class Content implements Contents {   
  6. private int i = 11*valueRate;   
  7. public int value() {   
  8. return i;   
  9. }   
  10. }   
  11.   
  12. protected class GDestination implements Destination {   
  13. private String label;   
  14. private GDestination(String whereTo) {   
  15. label = whereTo;   
  16. }   
  17. public String readLabel() {   
  18. return label;   
  19. }   
  20. }   
  21.   
  22. public Destination dest(String s) {   
  23. return new GDestination(s);   
  24. }   
  25. public Contents cont() {   
  26. return new Content();   
  27. }   
  28. }   


修改的部分用蓝色显示了。在这里我们给Goods类增加了一个private成员变量valueRate,意义是货物的价值系数,在内部类Content的方法value()计算价值时把它乘上。我们发现,value()可以访问valueRate,这也是内部类的第二个好处——一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!这是一个非常有用的特性,为我们在设计时提供了更多的思路和捷径。要想实现这个功能,内部类对象就必须有指向外部类对象的引用。Java编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。 

有人会问,如果内部类里的一个成员变量与外部类的一个成员变量同名,也即外部类的同名成员变量被屏蔽了,怎么办?没事,Java里用如下格式表达外部类的引用: 

outerClass.this 

有了它,我们就不怕这种屏蔽的情况了。 

静态内部类 
和普通的类一样,内部类也可以有静态的。不过和非静态内部类相比,区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套类很相像了,Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用这一点上,当然从设计的角度以及以它一些细节来讲还有区别。 

除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。 

局部内部类 
是的,Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。 

Java代码 
  1. public class Goods1 {   
  2. public Destination dest(String s) {   
  3. class GDestination implements Destination {   
  4. private String label;   
  5. private GDestination(String whereTo) {   
  6. label = whereTo;   
  7. }   
  8. public String readLabel() { return label; }   
  9. }   
  10. return new GDestination(s);   
  11. }   
  12.   
  13. public static void main(String[] args) {   
  14. Goods1 g= new Goods1();   
  15. Destination d = g.dest("Beijing");   
  16. }   
  17. }   


上面就是这样一个例子。在方法dest中我们定义了一个内部类,最后由这个方法返回这个内部类的对象。如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部,就可以这样做。当然,定义在方法中的内部类可以使设计多样化,用途绝不仅仅在这一点。 

下面有一个更怪的例子: 

Java代码 
  1. public class Goods2{   
  2. private void internalTracking(boolean b) {   
  3. if(b) {   
  4. class TrackingSlip {   
  5. private String id;   
  6. TrackingSlip(String s) {   
  7. id = s;   
  8. }   
  9. String getSlip() { return id; }   
  10. }   
  11. TrackingSlip ts = new TrackingSlip("slip");   
  12. String s = ts.getSlip();   
  13. }   
  14. }   
  15.   
  16. public void track() { internalTracking(true); }   
  17.   
  18. public static void main(String[] args) {   
  19. Goods2 g= new Goods2();   
  20. g.track();   
  21. }   
  22. }   


你不能在if之外创建这个内部类的对象,因为这已经超出了它的作用域。不过在编译的时候,内部类TrackingSlip和其他类一样同时被编译,只不过它由它自己的作用域,超出了这个范围就无效,除此之外它和其他内部类并没有区别。 

匿名内部类 
java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一样,当你只需要创建一个类的对象而且用不上它的名字时,使用内部类可以使代码看上去简洁清楚。它的语法规则是这样的: 

new interfacename(){......}; 或 new superclassname(){......}; 

下面接着前面继续举例子: 

Java代码 
  1. public class Goods3 {   
  2. public Contents cont(){   
  3. return new Contents(){   
  4. private int i = 11;   
  5. public int value() {   
  6. font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; b
    分享到:
    评论

相关推荐

    java 内部类使用(内部匿名类)

    - **匿名类简化**:对于只用一次的类,匿名内部类提供了简洁的写法。 在实际开发中,Java内部类的应用广泛,比如在Swing组件事件处理、线程编程(Thread或Runnable实现)、设计模式(如策略模式、装饰器模式)等...

    匿名类/内部类/本地类 解读

    最后,**本地类**与局部内部类类似,也是定义在方法或代码块内的类,但本地类的主要区别在于它可以声明为静态,这意味着它不依赖于外部类的实例。本地类通常用于实现线程或者回调函数等场景,例如: ```java public...

    java中的匿名内部类总结

    Java 中的匿名内部类是一种特殊的内部类,它没有名字,因此也称为匿名类。匿名内部类是一种简洁的编程方式,能够简化代码编写,但它也有一些限制和特点。 匿名内部类的定义 匿名内部类是指没有名字的内部类,它是...

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

    3. **匿名内部类与接口** 匿名内部类可以用来快速实现一个接口的所有方法,这对于实现简单的回调逻辑非常方便。例如,处理按钮点击事件: ```java button.setOnClickListener(new View.OnClickListener() { @...

    内部类 匿名内部类 内部接口 对比说明

    本文将详细探讨内部类、匿名内部类以及内部接口的对比和使用。 首先,让我们了解一下内部类的基本概念。内部类定义在其他类的内部,编译后会生成两个独立的类文件。内部类能够自由地访问外部类的所有成员,包括私有...

    Java4Android 35_内部类和匿名内部类

    1. **成员内部类**: 成员内部类与类中的成员变量地位相同,可以在类的任何地方声明。成员内部类可以访问外部类的所有成员,包括私有成员。 2. **局部内部类**: 定义在方法、构造器或块中的类被称为局部内部类。它的...

    Java 匿名内部类

    虽然标题没有明确指出,但值得注意的是,匿名内部类也可以作为类的成员,不过在这种情况下,它通常与外部类有密切的关系,可能访问外部类的成员变量和方法,包括private的。 5. **构造器**: 匿名内部类可以有...

    java 匿名内部类的使用规范

    Java匿名内部类是Java语言中一个独特且强大的特性,它允许我们在不需要定义一个单独的类的情况下创建类的实例。这在处理回调、事件监听、单例模式以及其他需要短时间内定义一个简单类的情况时非常有用。本篇文章将...

    匿名内部类代码

    描述中的"the different code of create factory"提到了工厂模式的创建方式多样性,这与匿名内部类的运用有关。工厂模式是一种设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们通过一个工厂方法来创建...

    Android开发匿名内部类

    在Java编程语言中,匿名内部类是一种特殊的类,它没有名字,通常用于简化代码和实现特定功能,如事件处理或接口快速实现。在Android开发中,匿名内部类的应用尤其广泛,因为Android框架中的许多组件(如按钮、文本...

    Android 匿名内部类作为事件监听类

    **匿名内部类与静态内部类的区别** 静态内部类可以独立于外部类存在,而匿名内部类必须依赖于外部类实例。这意味着,如果一个监听器需要访问外部类的成员变量,匿名内部类可以直接访问,但静态内部类则需要通过持有...

    java 内部类 局部内部类 匿名类 实例代码

    4. **静态内部类**:静态内部类与实例内部类不同,它不需要外部类的实例就可以被创建。静态内部类不能直接访问外部类的非静态成员,但可以通过外部类的实例来访问。以下是一个静态内部类的例子: ```java public ...

    匿名内部类核心重点知识讲解和经典例子讲解

    3. **匿名内部类与接口** - **实现接口**:匿名内部类可以直接实现一个接口,并提供接口中所有方法的实现。 - **单个接口实现**:如果只实现一个接口,可以省略`implements 接口名`,直接跟在`new`后面写大括号。 ...

    发两个匿名内部类使用的例子

    在Java编程语言中,匿名内部类是一种特殊的类,它没有名字,通常用于简化代码和实现特定功能。在标题“发两个匿名内部类使用的例子”中,我们将会探讨两种不同的场景,如何利用匿名内部类来解决问题。这篇博客文章的...

    匿名内部类实现接口回调

    这个"匿名内部类实现接口回调"的示例旨在演示如何通过匿名内部类来简化回调函数的实现。下面我们将详细探讨接口回调的概念、匿名内部类的使用以及它们在实际编程中的应用。 首先,让我们理解什么是接口回调。接口回...

    使用内部和匿名类优化Java代码

    因此,应谨慎选择何时使用内部类和匿名类,确保它们的使用符合设计原则和代码规范,同时避免常见的错误,如未正确处理内部类与外部类的引用关系,以及在不必要的情况下使用匿名类。通过理解这些特性的工作原理和适用...

    Java中的内部类和匿名类

    Java 中的内部类和匿名类 Java 中的内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在 C++ 里也有,那就是嵌套类(Nested Class)。内部类从表面上看,就是在类中又定义了一个类,而实际上并没有那么...

    16.java匿名内部类.zip

    16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名内部类.zip16.java匿名...

    Handler对象中使用匿名内部类或非静态内部类正确地释放消息避免内存泄漏或增加Native内存

    然而,不当使用Handler,尤其是结合匿名内部类或非静态内部类,可能导致内存泄漏和Native内存增加,这对应用性能和稳定性造成负面影响。 首先,我们要理解内存泄漏的概念。内存泄漏是指程序中已分配的内存没有被...

Global site tag (gtag.js) - Google Analytics