内部类小结

内部类,计算机面向对象程序设计概念。向对象程序设计中,可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型,即静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。内部类是JAVA语言的主要附加部分。内部类几乎可以处于一个类内部任何位置,可以与实例变量处于同一级,或处于方法之内,甚至是一个表达式的一部分。

一、 定义

放在一个类的内部的类我们就叫内部类。

二、内部类的分类

下面主要介绍一下java中的几种常见内部类:

1、静态内部类

静态内部类:在方法外部定义的内部类前面可以加上static关键字,从而成为Static Nested Class,它不再具有内部类的特性,所以,从狭义上讲,它不是内部类。Static Nested Class与普通类在运行时的行为和功能上没有什么区别,只是在编程引用时的语法上有一些差别,它可以定义成publicprotected、默认的、private等多种类型,而普通类只能定义成public和默认的这两种类型。在外面引用Static Nested Class类的名称为“外部类名.内部类名”。在外面不需要创建外部类的实例对象,就可以直接创建Static Nested Class,例如,假设Inner是定义在Outer类中的Static Nested Class,那么可以使用如下语句创建Inner类:

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

由于static Nested Class不依赖于外部类的实例对象,所以,static Nested Class能访问外部类的非static成员变量。当在外部类中访问Static Nested Class时,可以直接使用Static Nested Class的名字,而不需要加上外部类的名字了,在Static Nested Class中也可以直接引用外部类的static的成员变量,不需要加上外部类的名字。

具有的特点与用法:

    1).The simplest form of inner class,Can’t have the same name as the enclosing class

2).Compiled into a completely separate .class file from the outer class

3).Can access only static members and methods of the enclosing class, including private static members

4).Create an instance of a static inner class out of enclosing class:

new Outerclass.Innerclass()

在静态方法中定义的内部类也是Static Nested Class,这时候不能在类前面加static关键字,静态方法中的Static Nested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。

2、成员内部类

成员内部类:在方法体外面定义的内部类的访问类型可以是public,protecte,默认的,private4种类型,这就好像类中定义的成员变量有4种访问类型一样,它们决定这个内部类的定义对其他类是否可见;对于这种情况,我们也可以在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,

代码如下:

Outer outer = new Outer();

Outer.Inner1 inner1 = outer.new Innner1();

主要特点和用法如下:

1).Defined in an enclosing class without using the static modifier

2).Like instance variables

3).Can access all members of the enclosing class

4).Create an instance within the enclosing class

this.newInnerclass();

5).Create an instance out of the enclosing class

(new Outerclass()).new Innerclass();

6).Access members of the enclosing class within inner classes

Outerclass.this.member

3、局部内部类

局部内部类:在方法内部定义的内部类前面不能有访问类型修饰符,就好像方法中定义的局部变量一样,但这种内部类的前面可以使用finalabstract修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义,后使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符。

主要特点与用法如下:

1).Defined within the scope of a method, even smaller blocks within methods

2).The least used form of inner class

3).Like local variables, can’t be declared public, protected, private and static

4).Can only access final local variables

对于这些细节,只要在eclipse写代码试试,根据开发工具提示的各类错误信息就可以马上了解到。 

4、匿名内部类

匿名内部类:在方法体内部还可以采用如下语法来创建一种匿名内部类,即定义某一接口或类的子类的同时,还创建了该子类的实例对象,无需为该子类定义名称:

public class Outer
{
        public void start()
        {
              new Thread(new Runable(){
                            public void run(){};
                    }).start();
        }
}

三、内部类的作用
 1、内部类可以很好的实现隐藏。

平时我们对类的访问权限,都是通过类前面的访问修饰符来限制的,一般的非内部类,是不允许有 private protected权限的,但内部类可以,所以我们能通过内部类来隐藏我们的信息。可以看下面的例子。

//接口
package  hidecategory;
public  Interface DemoInterface{
	void demo();
}
//具体类
package  hidecategory;
public class OuterClass {
  
    private class InnerHideClass implements DemoInterface
    {
         public void demo()
         {
             System.out.println("这是一个测试");
         }
    }
    public InterfaceTest getInstance()
    {
        return new InnerHideClass();
    }
}
//客户端程序
package hidecategory;
public class DemoClient {
 
 public static void main(String args[])
 {
    OuterClass outer=new OuterClass();
    DemoInterface demoInt=outer.getInstance();
    demoInt.demo();
 }
}

客户端调用getInstance()方法能返回一个DemoInterface实例,但是我们并不知道这个实例是这么实现的。而且由于InnerHideClassprivate的,所以我们如果不看源代码的话根本看不到这个具体类的名字和它的具体实现,所以说它可以很好的实现隐藏。

2、内部类拥有外围类的所有元素的访问权限。

package inner;
 
public class OuterClass {
 
   private String name="OuterClassElement";
   private class InnerClass
   {
      public InnerClass()
      {
          System.out.println(name);
      }
   }
   public void test()
   {
    new InnerClass();
   }
   public static void main(String args[])
   {
       OuterClass outer=new OuterClass();
       outer.test();
   }
}

尽管上述的name是外部类OuterClass的private属性,但在内部类InnerClass中仍可以访问到,那么其他类型的属性当然也可以访问到,但具体情况会有所不同。

3、可是实现多重继承。

 个特点非常重要,基本上可以认为它是内部类存在的最大理由之一。正是由于他的存在使得Java的继承机制更加完善。大家都知道Java只能继承一个类,它的多重继承在我们没有学习内部类之前是用接口来实现的。但使用接口有时候有很多不方便的地方。比如我们实现一个接口就必须实现它里面的所有方法。而有了内部类就不一样了。它可以使我们的类继承多个具体类或抽象类。大家看下面的例子。

//父类一
 package multinherit;
 
public class SuperClass1 {
 
   public String name()
   {
       return "liutao";
   }
}
//父类二
package multinherit;
 
public class SuperClass2 {
 
    public int age()
    {
        return 25;
    }
}

//类三
 package multinherit;
 
public class MainClass
{
   private class InnerName extends SuperClass1
    {
        public String name()
        {
          return super.name();
        }
    }
    private class InnerAge extends SuperClass2
    {
       public int age()
       {
         return super.age();
       }
    }
   public String name()
    {
    return new InnerName().name();
   }
   public int age()
   {
       return new InnerAge().age();
   }
   public static void main(String args[])
   {
       MainClass mc=new MainClass ();
       System.out.println("姓名:"+mc.name());
       System.out.println("年龄:"+mc.age());
   }
}

从上面的代码可以看出,MainClass中分别出现了两个内部类 InnerName和InnerAge ,InnerName类又继承了SuperClass1,InnerAge继承了SuperClass2,这样我们的类三MainClas就拥有了SuperClass1和SuperClass2的方法和属性,也就间接地实现了多继承。

4、可以避免修改接口而实现同一个类中两种同名方法的调用。

    大家假想一下如果,你的类要继承一个类,还要实现一个接口,可是你发觉你继承的类和接口里面有两个同名的方法怎么办?你怎么区分它们??这就需要我们的内部类了。看下面的代码

//接口
 package innercls;
 
public interface Incrementable
{
 void increment();
}

//类 Increment
   package innercls;
 
public class Increment {
 
    public void increment()
    {
      System.out.println("Other increment()");
    }
    static void f(Increment f)
    {
        f.increment();
    }
 
}
//大家看上面加黑的部分,两个方法都是一样的。在看下面这个类要继承这两个类
//如果不用内部类
package innercls;
 
public class MyIncrement extends Increment implements Incrementable
{
public void increment()
      {
        //代码
       }
}
/*如果在某种情况下需要按照上述方式去做,那上述的increment()方法是类中的还是接口中的呢?这显然是不好区分的,而内部类却可以很好的解决该问题。*/
package innercls;
 
public class MyIncrement extends Increment
{
 private int i=0;
 private void incr()
 {
       i++;
       System.out.println(i);
 }
 private class InnerIncrement implements Incrementable
 {
      public void increment()
      {
        incr();
      }
 }
 Incrementable getCallbackReference()
 {
      return new InnerIncrement();
 }
}


 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值