Java内部类与接口、抽象

Java接口、抽象类、内部类  

1.接口(interface),接口被用来建立类与类之间关联的标准。
/* Java code */
public interface ITest{
      public void test();
}
public class TestImpl implements ITest{
      public void test(){
             System.out.println("test");
      }
}
2.抽象类(abstract class),只要类中有一个抽象方法,此类就被标记为抽象类。实际上抽象类除了被继承之外没有任何意义。

区别
1.
接口是公开(public)的,里面不能有私有的方法或变量,是用于让别人使用的,实现接口的一定要实现接口里定义的所有方法。
而抽象类是可以有私有方法或私有变量的,实现抽象类可以有选择地重写需要用到的方法,但是必须实现里面所有的抽象方法。
2.
抽象类在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。
但是,一个类却可以实现多个interface(java中实现多重继承的方法之一)。
3.
抽象类中可以有自己的数据成员,也可以有非abstarct的成员方法。
而在接口中,只能够有静态的不能被修改的数据成员(也就是必须是 static final的,不过在 interface中一般不定义数据成员),而且所有的成员方法都是抽象的。
4.
抽象类和接口所反映出的设计理念不同。
其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。(组合是"has a"关系)
5.
接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。
抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。不是很建议具体类直接实现接口的。还有一种设计模式是面向接口编程,而非面向实现编程。

其实接口是抽象类的延伸,可以将它看做是纯粹的抽象类,就是说接口比抽象类还抽象,还有设计接口的目的就是为了实现C++中的多重继承,不过java团队设计的一样更有趣的东西来实现这个功能,那就是内部类(inner class)。

/* Java code */
public class OuterClass{//外部类
       private class InnerClass{}//内部类
}


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

二.作用
1.内部类可以很好的实现隐藏,也就是封装性。一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
2.内部类拥有外围类的所有元素的访问权限
3.可是实现多重继承(这个特点非常重要,个人认为它是内部类存在的最大理由之一)
4.可以避免修改接口而实现同一个类中两种同名方法的调用


三、   例子

1.实现隐藏

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

接口

package insidecategory;

public interface Incrementable

{

  void increment();

}

具体类

package insidecategory;

public class Example {

  

    private class InsideClass implements InterfaceTest

    {

         public void test()

         {

             System.out.println("这是一个测试");

         }

    }

    public InterfaceTest getIn()

    {

        return new InsideClass();

    }

}

上面加粗的部分是内部类,访问修饰符是private

客户端程序

package insidecategory;

public class TestExample {

  public static void main(String args[])

  {

    Example a=new Example();

    InterfaceTest a1=a.getIn();

    a1.test();

  }

}

加粗的那部分就是客户端调用的代码,从这段代码里面我只知道Example的

getIn()方法能返回一个InterfaceTest 实例但我并不知道这个实例是这么实现的。而且由于InsideClass 是private的,所以我们如果不看代码的话根本看不到这个具体类的名字,所以说它可以很好的实现隐藏。

2.可以无条件地访问外围类的所有元素

package insidecategory;

public class TagBean {

 private String name="liutao";

   private class InTest

   {

      public InTest()

      {

          System.out.println(name);

      }

   }

   public void test()

   {

    new InTest();

   }

   public static void main(String args[])

   {

       TagBean bb=new TagBean();

       bb.test();

   }

}

看上面加粗部分,name这个变量是在TagBean里面定义的私有变量。这个变量在内部类中可以无条件地访问System.out.println(name);

 3.可以实现多重继承

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

类一

  package insidecategory;

public class Example1 {

   public String name()

   {

       return "liutao";

   }

}

类二

package insidecategory;

public class Example2 {

    public int age()

    {

        return 25;

    }

}

类三

 package insidecategory;

public class MainExample

{

   private class test1 extends Example1

    {

        public String name()

        {

          return super.name();

        }

    }

    private class test2 extends Example2

    {

       public int age()

       {

         return super.age();

       }

    }

   public String name()

    {

    return new test1().name();

   }

   public int age()

   {

       return new test2().age();

   }

   public static void main(String args[])

   {

       MainExample mi=new MainExample();

       System.out.println("姓名:"+mi.name());

       System.out.println("年龄:"+mi.age());

   }

}

大家注意看类三,里面分别实现了两个内部类 test1,和test2 ,test1类又继承了Example1,test2继承了Example2,这样我们的类三MainExample就拥有了Example1和Example2的方法和属性,也就间接地实现了多继承。


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

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

接口

 package insidecategory;

public interface Incrementable

{

  void increment();

}

类  MyIncrement

   package insidecategory;

public class MyIncrement {

    public void increment()

    {

      System.out.println("Other increment()");

    }

    static void f(MyIncrement f)

    {

        f.increment();

    }

}

大家看上面加黑的部分,两个方法都是一样的。在看下面这个类要继承这两个类

如果不用内部类

package insidecategory;

public class Callee2 extends MyIncrement implements Incrementable

{

public void increment()

      {

        //代码

       }

}

想问一下大家increment()这个方法是属于覆盖MyIncrement这里的方法呢?还是Incrementable这里的方法。我怎么能调到MyIncrement这里的方法?显然这是不好区分的。而我们如果用内部类就很好解决这一问题了。看下面代码

package insidecategory;

public class Callee2 extends MyIncrement

{

  private int i=0;

  private void incr()

  {

       i++;

       System.out.println(i);

  }

  private class Closure implements Incrementable

  {

      public void increment()

      {

        incr();

      }

  }

  Incrementable getCallbackReference()

  {

      return new Closure();

  }

}

我们可以用内部类来实现接口,这样就不会与外围类的方法冲突了。

内部类的深入学习 

一、内部类自动拥有对其外围类的所有成员的访问权。

当某个外围类对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用。然后,在你访问此外围了的成员时,就是用那个引用来选择外围类的成员。但是如果内部类是非static的,内部类的对象只能在与其外围类的对象相关联的情况下才会被创建。继承内部类的时候也需要其外围类的对象引用,否则继承无效。

二、.this.new关键字

.this:在内部类中生成对其外围类的引用。一般可以使用外围类的名字后面紧跟圆点和this

.new:如果想告知某些其他对象,去创建某个内部类的对象,必须在new表达式中提供对其他外部类对象的引用,这就需要使用.new语法。例如:

Public class DotNew{}

       Public class Inner{}

}

Public static void main(String args[]){

       DotNew dn=new DotNew();

       DotNew.Inner dni=dn.new Inner();

       //dn.new DotNew.Inner(); 这是错误的

}//在拥有外部了对象之前是不可能创建内部类对象的(非Static内部类)

 

三、内部类可以向上转型(Upcasting)为其基类,或者接口。这时,内部类得到了对接口的引用,能够方便地隐藏实现细节。

四、内部类可以定义在方法和作用域中(需要慢慢地理解)

a)         可以定义在一个方法中

b)        可以定义在作用域中

c)         匿名内部类可以实现一个接口

d)        匿名类可以扩展有非默认构造器的类

e)         匿名类可以执行字段初始化

f)         匿名类可以通过实例初始化实现构造(匿名类不可能有构造器)

五、 嵌套类

如果不需要内部类对象与其外围类对象之间有联系,那么可以将内部类声明为static普通的内部类自动获取对外围类的引用,而嵌套类具有static的特性,不依赖外围类对象的建立,也没有指向外围类的对象。

1、  要创建嵌套类的对象,不需要外围类的对象;嵌套类中不可以使用this引用;

2、  不能从嵌套类的对象中访问非static的外围类对象;

3、  嵌套类有许多类似static的属性,因为嵌套类本身就是static的,嵌套类可以有static的数据和static字段,还可以包含static的嵌套类,而普通内部类是不可以的。

4、  嵌套类可以作为接口的一部分,而一般情况下,接口内是不允许有任何具体的代码的;

5、  嵌套类可以作为一些公共代码,使得他们可以被某个接口的所有不同实现所共用;

6、  可以使用嵌套类在每个类中都写一个Main()方法,来测试这个类。

7、  在多层嵌套类中,最深层的嵌套类可以透明底访问它所嵌入的外围类的所有成员

六、为什么需要内部类?

每个内部类都能独立地继承自一个(接口)的实现,所以无论外围类是否已经继承了某个(接口的)的实现,对于内部类都没有影响。

普通的类无法实现对抽象类和普通类的多重继承,而采用内部类可以实现,这在有时候是很有用的。内部类使得多重继承的解决方案变得更加完整。接口的实现解决了部分问题,而内部类有效地实现了“多重继承”,即:内部类可以继承非接口类型。

用内部类实现多个接口的意义:

1、  内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对象的信息相互独立;

2、  在当个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类;

3、  创建内部类对象的时刻并不依赖于外围类对象的创建;

4、  内部类并没有令人迷惑的“is-a”关系,它就是一个独立的类。




你可能感兴趣的:(java,设计模式,编程,String,Class,interface)