内部类

2018-12-12  本文已影响0人  ClawHub的技术分享

如果有幸能让您看到我写的东西,要先跟您说明一下,我这个都是在别人那里看来的,只作为自己学习的一个总结,希望大家能过去看看下方的原文,比我写的好多了,最好给大神一个关注!

ID:云开的立夏

原文链接:http://www.cnblogs.com/hysum/p/7101974.html

内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。

  1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

  2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据。

  3. 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便。

  内部类可分为成员内部类,静态内部类,方法内部类,匿名内部类 。

成员内部类

a.成员内部类实例:

运行结果为:

从上面的代码中我们可以看到,成员内部类的使用方法:

  1. Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如 public 、 protected 、 private 等

  2. Inner 类中定义的 test() 方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer 类中的私有属性a

  3.定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( );

  4. 编译上面的程序后,会发现产生了两个 .class 文件

其中,第二个是外部类的 .class 文件,第一个是内部类的 .class 文件,即成员内部类的 .class 文件总是这样:外部类名$内部类名.class

  5. 外部类可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。但是不能直接访问内部类成员变量和方法.

b.有相同名字的成员变相或者方法怎么办

         如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,可以使用 this 关键字。

运行结果:

静态内部类

静态内部类是 static 修饰的内部类,这种内部类的特点是:

  1.静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问。

  2.如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员。

  3.创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();

运行结果:

方法内部类

方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用。

运行结果:

匿名内部类

  匿名类是不能有名称的类,所以没办法引用他们。必须在创建时,作为new语句的一部分来声明他们。

  但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口。

a.抽象方法中使用匿名内部类

b.接口中使用匿名内部类

运行结果(两个一致):

c.匿名内部类总结
1.使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。

2.匿名内部类中是不能定义构造函数的。

3.匿名内部类中不能存在任何的静态成员变量和静态方法。

4.匿名内部类为局部内部类(即方法内部类),所以局部内部类的所有限制同样对匿名内部类生效。

5.匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

内部类总结

java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题——没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。

例子1:

public interface Contents {

     int value(); 

    }  

    public interface Destination { 

     String readLabel(); 

    }

例子2:

public class Goods {

      private valueRate=2;  

     private class Content implements Contents { 

       private int i = 11 * valueRate; 

      public int value() { 

       return i; 

      } 

     }  

     protected class GDestination implements Destination { 

      private String label; 

      private GDestination(String whereTo) { 

       label = whereTo; 

      } 

      public String readLabel() { 

       return label; 

      } 

     }  

     public Destination dest(String s) { 

      return new GDestination(s); 

     }  

      public Contents cont() { 

      return new Content(); 

     } 

    }

在这个例子里类 Content 和 GDestination 被定义在了类 Goods 内部,并且分别有着 protected 和 private 修饰符来控制访问级别。Content 代表着 Goods 的内容,而 GDestination 代表着 Goods 的目的地。它们分别实现了两个接口Content和Destination。在后面的main方法里,直接用 Contents c 和 Destination d进行操作,你甚至连这两个内部类的名字都没有看见!这样,内部类的第一个好处就体现出来了——隐藏你不想让别人知道的操作,也即封装性。

非静态内部类对象有着指向其外部类对象的引用

修改上面的例子:

public class Goods {

      private valueRate=2;  

     private class Content implements Contents { 

       private int i = 11 * valueRate; 

      public int value() { 

       return i; 

      } 

     }  

     protected class GDestination implements Destination { 

      private String label; 

      private GDestination(String whereTo) { 

       label = whereTo; 

      } 

      public String readLabel() { 

       return label; 

      } 

     }  

     public Destination dest(String s) { 

      return new GDestination(s); 

     }  

      public Contents cont() { 

      return new Content(); 

     } 

    }

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

上一篇 下一篇

猜你喜欢

热点阅读