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
上一篇:数据结构第六章学习小结


下一篇:L1-007 念数字 (10分)