JavaSE基础——面向对象3:接口与内部类---007

JavaSE基础——面向对象3:接口与内部类

六、接口

1. 什么是接口?

JAVA编程语言中,接口是一个抽象类型,是抽象方法的集合

接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。类的继承只能单继承,但可以通过接口实现(伪)多继承。

  • 接口代表一种能力,实现接口,则表示具备了某种功能

  • 接口代表一种规范,在实现接口的时候必须遵循相应的规范,比如说重新实现方法的时候参数的要求、返回值的要求等等

接口中定义了一些抽象方法,如果类要实现该接口,则必须给出这些抽象方法的具体实现。因此说接口时一种能力。

2. 接口的特点

  • 使用interface关键字声明接口

  • 接口中可以定义变量,但接口中的变量会隐式地指定为public static final型变量

  • 接口主要是一系列抽象方法的集合,接口中的方法会被隐式地指定为 public abstract 类型

  • 接口中都是抽象方法,只有方法名,没有方法体。只能由实现接口的类来重写接口中抽象方法的具体实现

  • 接口没有构造方法,不能实例化。

  • 接口可以继承接口,而且还可以多继承。

  • 类使用implements关键字实现接口。在类声明中Implements关键字放在class声明后面。

3. 接口的实现

3.1 接口实现示例

package com.oop_extends.www;
//声明一个接口,接口名称为Sing
interface Sing {
   
   int vol = 10;//接口中定义的变量会隐式地指定为 public static final变量,一般不会再接口中声明变量
   //public static final int vol = 10;
   boolean isSing = true;
   //接口主要是一系列抽象方法的集合,接口中的方法会被隐式地指定为 public abstract 类型
   //因为方法都是抽象方法,因此接口里的方法也都是只有方法名,没有方法体,需要实现接口的类来提供方法的具体细节实现
   void singSong(People people);
}


abstract class People {  //声明一个抽象类,名称为People
   
   abstract void speak();//声明一个抽象方法,speak
}


class Boy extends People {  //继承抽象类要重写父类中的抽象方法speak
 
   @Override
   void speak() {
       System.out.println("男孩说话");
  }
}


class Singer extends People implements Sing {//创建一个子类Singer,继承于父类People,实现接口Sing
   //当类要实现接口的时候,除非该类是抽象类,否则该类要重写实现接口里的所有抽象方法
   //重写sing接口中的singSong方法,
   @Override
   public void singSong(People people) {
       //在实现接口的抽象方法singSong时,调用父类的抽象方法speak
       this.speak();
  }
 
   @Override
   void speak() { //对于父类中的抽象方法,子类要重写给出具体实现
       System.out.println("歌手唱歌");
  }
}


public class Jiekou {
   public static void main(String[] args) {
       //实例化一个Singer类的对象
       //调用Singer类所实现的接口Sing中的singSong方法,
       //实例化一个Boy类对象,将其作为参数传递给singSong方法
       new Singer().singSong(new Boy());
       //singSong的参数类型为People,接收boy后自动转换
       //转换后执行当前类的speak方法,当前类为Singer,因此执行”歌手唱歌“
  }
}
--------------------------------------------------
运行结果:
   歌手唱歌

可以看到,编写接口的方式和类很相似。但是接口不是类

 

3.2 实现接口的注意点

类(实现接口)需要(重写接口)中声明的抽象方法。但是重写接口中声明的方法时,需要注意以下规则:

  • 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。

  • 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。

  • 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。

在实现接口时也应注意一些规则

  • 一个类可以同时实现多个接口,将接口名依次放在implements关键字后面,类里面要重写所有接口的抽象方法。

  • 一个类只能继承一个类,但是能实现多个接口。

  • 一个接口能继承另一个接口,这和类之间的继承比较相似。

5. 接口的继承

一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。

public interface Sports
{
  public void setHomeTeam(String name);
  public void setVisitingTeam(String name);
}
//实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。
public interface Football extends Sports
{
  public void homeTeamScored(int points);
  public void visitingTeamScored(int points);
  public void endOfQuarter(int quarter);
}
//Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。
public interface Hockey extends Sports
{
  public void homeGoalScored();
  public void visitingGoalScored();
  public void endOfPeriod(int period);
  public void overtimePeriod(int ot);
}
//java支持多继承,因此下面语句也是合法的
public interface Hockey extends Sports, Event

 

七、内部类

1.1 什么是内部类?

内部类就是在一个类的内部再定义一个类。比如,A类中定义了一个B类,则B类相对于A类来说称为内部类,A类相对于B类来说就是一个外部类。

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

使用内部类最大的优点:解决多重继承的问题

  • 内部类提供了更好的封装,除了该外围类,其他类都不能访问。

1.2 内部类主要分为:

内部类分类

  • 成员位置:在成员位置定义的类,被称为成员内部类

  • 局部位置:在局部位置定义的类,被称为局部内部类

  • 成员内部类

  • 静态内部类

  • 局部内部类

  • 匿名内部类

 

内部类访问特点

  • 内部类可以直接访问外部类成员,包括私有的

  • 外部类要访问内部类成员,需先创建对象

public class Outer {
   int num = 10;
   private int a = 100;
   //定义成员内部类
   class Inner {
       int b = 109;
       public void innerShow() {
           System.out.println("内部类的show方法");
      }
       //内部类可以直接访问外部类的成员,包括私有
       public void innerTest(){
           System.out.println(num);
           System.out.println(a);
           outerShow();
           outerTest();
      }
  }
   public void outerShow() {
       System.out.println("这是外部类的show方法");
  }
   private void outerTest() {
       System.out.println("这是外部类的show方法");
  }
   //外部类,想要访问内部类的成员,得创建内部类的对象
   public void method(){
       //创建内部类的对象
       Inner inner = new Inner();
       System.out.println(inner.b);
       inner.innerShow();
  }
}
//测试类
public class MyTest {
   public static void main(String[] args) {
       Outer outer = new Outer();
       System.out.println(outer.num);
       outer.outerShow();
       System.out.println("----------------");
       //使用成员内部类的属性和方法
       //创建成员内部类的语法
       Outer.Inner inner=new Outer().new Inner();
       System.out.println(inner.b);
       inner.innerShow();
       System.out.println("---------------");
       outer.method();
  }
}
//输出
   10
   这是外部类的show方法
   ----------------
   109
   内部类的show方法
   ---------------
   109
   内部类的show方法
   

成员内部类

  • 访问格式:外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

//定义类
class Body {//外部类,身体

   private boolean life= true;//生命状态
   
    public class Heart {      //内部类,心脏

   public void jump() {
        System.out.println("心脏噗通噗通的跳")
           System.out.println("生命状态" + life); //访问外部类成员变量
      }
  }
}

public static void main(String[] args) {//访问内部类
   //创建内部类对象
   Body.Heart bh = new Body().new Heart();
   //调用内部类中的方法
   bh.jump();
}

成员内部类的修饰符

private 为了保证数据的安全性 static 为了方便访问数据

注意:静态内部类访问的外部类数据必须用静态修饰,成员方法可以是静态的也可以是非静态的

 

class Outer {
       public int num = 10;
       class Inner {
           public int num = 20;
           public void show() {
               int num = 30;
               System.out.println(num); //30
               System.out.println(this.num); //20
               System.out.println(new Outer().num); //10
                System.out.println(Outer.this.num);// 和上面new Outer().num一个意思
          }
      }
  }
   class InnerClassTest {
       public static void main(String[] args) {
           Outer.Inner oi = new Outer().new Inner();
           oi.show();
      }    
  }

 

局部内部类

局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问(在方法内部定义类)

  • 定义格式

class 外部类 { 
   修饰符 返回值类型 方法名(参数) {
class 内部类 {
//其他代码
      }
  }
}

访问方式

在外部类方法中,创建内部类对象,进行访问

package com.inner;

public class Demo02 {
    int a = 100;
   public void show(int a ){
       int num =0;
       class nei{
           public void neiShow() {
               //局部内部类,访问外部类的局部变量,局部变量必须加上final修饰,JDK1.8 默认就加上了
               System.out.println(num);
               System.out.println(a);
          }
      }
       nei nei=new nei();
       nei.neiShow();

  }




   public static void main(String[] args) {
       Demo02 demo02= new Demo02();
       demo02.show(55);




  }
}


----------------------------------
   0
   55

 

匿名内部类

  • 匿名内部类的作用:临时定义某一指定类型的子类 ,定义后即刻创建刚刚定义的这个子类的对象

  • 格式:

    new 父类或接口(){

    //进行方法重写

    };

public static void main(String[] args) {
       //匿名内部类:是局部内部类的简写
       //匿名内部类,本质上是一个对象,是谁的对象,是实现了该接口或继承了该抽象类的子类对象
       new AA(){
           @Override
           public void show() {
               System.out.println("重写了show方法");
          }
      }.show();
  }
}
abstract class AA{
   public abstract void show();
}
//输出:重写了show方法

 

 

Java权限修饰符

一、四种权限修饰符

private(私有的) , 默认 , protected(受保护的) , public(公共的)

               本类         同一个包下(子类和无关类)    不同包下(子类)      不同包下(无关类)
private         Y        
默认             Y               Y
protected       Y               Y                      Y
public          Y               Y                      Y                  Y

二、类及其组成所使用的常见修饰符

  • 修饰符

    • 权限修饰符:public、protected、默认、private

    • 状态修饰符:static、final

    • 抽象修饰符:abstract

  • 修饰类的关键字

    • 权限修饰符:默认修饰符,public

    • 状态修饰符:final

    • 抽象修饰符:abstract

  • 修饰成员变量的关键字

    • 权限修饰符:private、默认的、protected、public

    • 状态修饰符:static,final

  • 修饰成员变量的关键字

    • 权限修饰符:private、默认的、protected、public

    • 状态修饰符:static、final

  • 修饰构造方法的关键字

    • 权限修饰符:private、默认的、protected、public

  • 修饰成员方法的关键字

    • 权限修饰符:private、默认的、protected、public

    • 状态修饰符:static、final

    • 抽象修饰符:abstract

  • 除此以外的组合规则

    • 成员变量:public static final (接口)

    • 成员方法:public static public abstract public final

    •  

 

上一篇:997?007?准点下班?连数据结构与算法都整不明白,有选择余地?


下一篇:Python练习007