您的位置:首页 - 教程 - Java - 正文
java学习之接口、多态和内部类

接口是一组行为的规范、定义。接口是面向对象编程体系中的思想精髓之一,使用接口可以让我们的程序更加利于变化。

接口的格式:

interface 接口名称{

    全局变量;

    抽象方法;

}

接口中的成员修饰符是固定的,成员常量用public static  final修饰;成员函数用public  abstract修饰,接口的出现将“多继承”通过多实现来体现。接口的使用也有一定的规则:接口可以继承多个接口,一个类中可以实现接口和多接口,抽象类实现接口可以不实现方法;接口中的所有实现方法的访问权限都是public;接口中定义的属性都是常量。java中用interface关键字来修饰接口。当一个抽象类中的方法都是抽象的时候,就可以将该类用另一种方式表现出来,就是接口。

 interface   Demo{
 
     public static final  x=9     public  abstract   void  show();
 
 }

注意:类与类之间是继承关系,类与接口是实现关系。接口不可以实例化:只能由实现了接口的子类并覆盖接口中的所有方法后,该子类才可以实例化,否则,该子类是一个抽象类。

 interface  Animal{
    String  name;
    String   age;
 
    public void eat();
   public void  speak();
 
 }
 class  Cat{
 
    public void  eat(){
         System.out.println("我爱吃鱼!");
     }
 
 
     public  void   speak(){
          System.out.println("喵喵~~~·");
     }
 }

 

接口的四大特点:1、接口是对外暴露的规则;2、接口是编程的功能扩展;3、接口的出现降低了耦合性;4、接口可以用来多实现。

抽象类与接口的异同点:

    相同点:都是不断向上抽取而来的。

    不同点:抽象类需要被继承,而且只能单继承,接口需要被实现,可以多实现 ;抽象类中可以定义抽象方法和非抽象方法,而接口中只能定义抽象方法,必须由子类去实现;抽象类的继承,是is  a关系,定义体系基本共性内容,而接口的实现是like  a 关系,定义体系额外功能。

什么叫接口回调?

   可以把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量中,那么该接口变量就可以调用被类实现的接口中的方法。

 

多态性:多态是面向对象的三大特性之一,多肽主要体现在两个方面:一是方法的重载与重写。二是对象的多态性。多态就是某一类事物的多种存在形态。

例如:动物,猫,狗

1、猫这个对象对应的类型是猫类型。

猫  X   =   new   猫 ();

2、 猫也是动物的一种,也可以把猫称为动物。

动物   Y   =   new   猫 ();

父类型的引用指向了子类对象。一个对象,两种形态;猫这类事物即具备着猫的形态,又具备着动物的形态。这就是对象的多态性。简单来说就是一个对象对应着不同类型。那么使用多态有什么利弊呢?使用多态不仅提高了代码的扩展性,前期定义的代码可以使用后期的内容。当然,使用多态在前期定义的内容不能使用(调用)后期子类特有的内容。

当然,使用多态也有着前提:代码中必须有关系,即继承或者实现;二是要有覆盖(只发生在函数上,成员变量没有)。

对象的多态性:对象的多态性是从继承关系中的多个类而来。

向上转型:将子类实例转化为父类实例

            格式:父类   父类对象  =  子类实例  ; ------>自动转化

如:int  i='a';  因为char的容量比int小,所以可以自动完成。

向下转型:将父类实例转化为子类实例;

            格式:子类   子类对象=(子类)父类实例; -------->强制转换

如:char  c=(char)97;  因为整形4个字节比char2个字节大,所以要强制转换。

 //例如
 Animal  a=new  Cat();   //自动提升,特有功能无法访问
 
 Cat  c= (Cat)  a;   //向下转型的目的是为了使用子类中的特有功能。

多态的特点:

1)、成员变量:

编译时,参考引用型变量所属的类中是否有调用的成员变量,有通过,没有则失败;运行时,参考引用型变量所属的类中是否有调用的成员变量,并运行所属类中的的成员变量。

简单来说:编译和运行都参考等号的左边。

2)、成员函数:

编译时,参考引用型变量所属的类中是否有调用的成员变量,有通过,没有则失败;运行时,参考的是对象所属的类中是否有调用的函数。

简单来说:编译看左边,运行看右边。

3)、静态函数:

编译时,参考引用型变量所属的类中是否用调用的静态函数。运行时,参考引用型变量所属的类中是否用调用的静态函数。

简单来说:编译和运行都看左边。其实对于静态方法不需要对象的,直接类名调用即可。

 

在多态中,还有个关键字需要注意:instanceof关键字。

语法格式:对象 instanceof 类型------返回的是Boolean类型值

该语句一般用于判断一个对象是否为某一个类的实例,是返回true,否则返回false。

使用instanceof关键字的父类的设计法则:

通过instanceof关键字,我们可以检查对象的类型,但是如果一个父类中的子类过多,判断繁琐,那么如何设优计父类呢?

1)、父类通常设计为抽象类或者接口,其中优先考虑接口,接口不能满足才考虑抽象类。

2)、一个集体的类尽可能不去继承另一个具体的类,这样的好处是无需检查对象是否为父类的对象。

 public  static  void method(Animal  a){
     a.eat();
     if(a instance  Cat){
       //instance用于判断对象的具体类型
       //通常在向下转型用于健壮性的判断。
       Cat  c=(Cat) a;
       c.catchMouch();
     }
 }

 

内部类:将一个类定义在另一个类的里面,里面的那个类就称为内部类(内置类,嵌套类)。内部类访问的特点:内部类可以直接访问外部类中的成员,包括私有成员;而外部类要访问内部类的成员,必须要建立内部类的对象。可以在外部创建内部类对象:内部类除了可以在外部类中产生实例化对象,也可以在外部类的外部来实例化。

方法内部类:内部类可以作为一个类的成员外,还可以把类放在方法内定义。

成员内部类的格式:

 class  Quter{
 
     public  void  print(){
       //在外部类实例化内部类对象,并调用方法
       Inner  inner = new Inner(“成员内部类”);
      inner。print();
     }
    class  Inner{}
 
 }

 

注意:

1)、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。

2)、方法内部类对象不能使用该内部类的所在的方法的非final局部变量。内部类只能访问局部中被final修饰的局部变量。

静态内部类:

  静态的含义是该内部类可以像其他静态成员一样,没有外部类对象的时候,,也能够访问它,静态嵌套类仅能访问外部类的的静态成员和方法。

class Quter{
    static  class Inner{ }
    
     }
class   Test{
     public static void  main(String[] args){

       Quter.Inner n=new  Quter.Inner();                    
    }

}

内部类访问的特点:

1、内部类可以直接访问外部类的成员。那是因为内部类持有了外部类的引用。

2、外部类要访问内部类,要建立内部类对象

   在分析事物时,发现该事务在描述上还有事物,而且该事物还在访问被描述事物的内容,这是还有的事物就定义为内部类。

class Quter{
    private String name;
     public void show(){}
    public static void method(){}
  class Inner{
      int age;
     public void add(int a,int b){}
      
   }

 static class Nner{

      public void shou(){}
       static void function(){}
 }
}
class Test{
    public static void main(String[] args){
      //直接访问外部类中的成员
       Quter out=new Quter();
       out.show();
       System.out.println(out.name);

      //直接访问外部类中的内部类的中的成员
      Quter.Inner  in=new Quter().new Inner();
       in.show();

        //如果内部类是静态的,相当于一个外部类
        Quter.Nner inn=new Quter.Nner();
         inn.shou();

           
            //如果内部类是静态的,成员也是静态的
            Quter.Nner.function();

    }

}

 

匿名内部类:

   匿名内部类就是没有名字的内部类,一般分为三种情况:1)继承式的匿名内部类。2)接口式的匿名内部类 。3)参数式的匿名内部类

//继承式的匿名内部类
new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
}.start();


//
接口式的匿名内部类 public void print2(){ Child c=new Child(){ public void desc(){ System.out.println("接口式匿名内部类"); } } } //参数式的匿名内部类 outer.print3(new Child(){ public void desc(){ System.out.println(“参数式的匿名内部类”); } });

匿名内部类是内部类的简写格式,所有一些规则:即是内部类必须继承或者实现一个外部类或者接口。

使用个匿名内部类的规则:内部类中不能有构造函数,只有一个实例;不能定义任何静态成员,静态方法;修饰词不能式public,protected,private,static;内部类一定是在new后面,用其隐含实现一个接口或者实现一个类;匿名内部类都是局部的,所以局部内部类的所有权限都生效。

匿名内部类的作用:每个内部类都能独立的继承自一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类提供可以继承多个具体的或抽象的类的能力,内部类使能多重继承的方案变得完整。接口解决了部分问题,内部类有效的解决了多重继承的问题。

匿名内部类的使用场景之一:当函数参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类作为实际参数进行传递。

public  void  method(){

    Inner   in=new  Inner(){

       public void  show1(){}
 
       public void show2(){}
     
    }

    in.show1();

    in.show2();
} 

评论: