Java复习6 抽象类、接口、内部类、匿名类

6. 抽象类、接口、内部类

6.1 抽象类

6.1.1 声明抽象类
public abstract class Test{
  abstarct void run();//没有方法体
}
  1. 抽象类不能实例化,即不能new一个对象,但可以用来声明变量类型,如Test myTest。
  2. 抽象类可以有或没有抽象方法,但有抽象方法的类必须定义为抽象类。
  3. 抽象方法没有方法体,而不是方法体为空。
  4. 当一种方法声明为抽象方法时,意味着这种方法必须被子类的方法所覆盖,否则子类仍然是抽象的。
  5. abstract不能与private、static、final或native并列修饰同一种方法。
  6. 抽象类可以有构造函数。
6.1.2 继承抽象类
  1. 子类继承抽象类,其实现方法的权限必须大于等于父类方法的权限。如抽象方法权限为默认,则子类可为默认,protected,public。
  2. 子类如果是非抽象类,那么子类必须覆盖重写父类当中的所有方法。子类如果是抽象类,可以选择性覆盖。于6.1.1中4同义。
  3. 抽象类的子类可以是抽象类,也可以是非抽象类。

6.2 接口

6.2.1 声明接口

接口本身也具有数据成员、抽象方法、默认方法和静态方法,但它与抽象类有下列不同。
(1)接口的数据成员都是静态的且必须初始化,即数据成员必须是静态常量。 (2)接口中除了声明抽象方法外,还可以定义静态方法和默认方法。

接口的理解:

  • 接口是抽象方法的集合,一个类通过继承接口的方式,从而来继承接口的抽象方法。
  • 接口不能实例化对象,没有构造方法。
  • 接口中的所有方法必须是抽象方法。
  • 接口不是被类继承而是被类实现。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错);接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
  • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
    抽象类和接口的区别
    注:1. JDK 1.8 以后,接口里可以有静态方法和方法体了。 2.JDK 1.8 以后,接口允许包含具体实现的方法,该方法称为"默认方法",默认方法使用 default 关键字修饰。更多内容可参考 Java 8 默认方法。3.JDK 1.9 以后,允许将方法定义为 private,使得某些复用的代码不会把方法暴露出去。
  • 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
    接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
    接口中的方法都是公有的。
  • 接口的继承和多继承
    Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。相似的,实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。
  1. 接口的继承
// 文件名: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}
 
// 文件名: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}
 
// 文件名: Hockey.java
public interface Hockey extends Sports
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}
  1. 接口的多继承:public interface Hockey extends Sports, Event
    参考:菜鸟教程接口接口定义与实现
    例题:下列说法错误的是(B)
    A.类只能继承一个父类,但是可以实现多个接口
    B.抽象类自身可以定义成员而接口不可以
    C.抽象类和接口都不能被实例化(忽略匿名内部类)
    D.一个类可以有一个父类和多个接口
    解释:B选项中,java 接口中可以定义成员变量,且必须是 static final的。

6.3 内部类

在类或接口内声明的类。方法内也可以声明内部类,这是局部内部类。不过局部内部类访问局部变量时,该局部变量必须有final修饰,访问类变量、实例变量无此要求。

  • 内部类一旦编译成功,就会成为完全不同的两个类,分别为outer.class和outer$inner.class类。所以内部类的成员变量/方法名可以和外部类的相同。
  • 要访问内部类,可以通过创建外部类的对象,然后创建内部类的对象来实现。
  • 成员内部类里面为什么不能有静态成员和方法?
    非静态内部类不能有静态成员!
    成员内部类必须先实例化外部类对象然后再实例化成员内部类;
  • 嵌套类有两种类型:非静态内部类 静态内部类
  • 非静态内部类:
    非静态内部类是一个类中嵌套着另外一个类。 它有访问外部类成员的权限, 通常被称为内部类。
class OuterClass {
  int x = 10;
 /***私有的内部类**
 如果你不希望外部类被内部类访问,可以将内部类声明为private
 private class InnerClass {
    int y = 5;
  }*/
  class InnerClass {
    int y = 5;
  }
}

public class MyMainClass {
  public static void main(String[] args) {
    OuterClass myOuter = new OuterClass();
    OuterClass.InnerClass myInner = myOuter.new InnerClass();
    System.out.println(myInner.y + myOuter.x);
  }
}

输出结果:15

  • 静态内部类:
    注:静态内部类无法访问外部类的成员。
class OuterClass {
  int x = 10;

  static class InnerClass {
    int y = 5;
  }
}

public class MyMainClass {
  public static void main(String[] args) {
    OuterClass.InnerClass myInner = new OuterClass.InnerClass();
    System.out.println(myInner.y);
  }
}

输出结果为:5

另外还有:

  • 局部内部类
    指内部类定义在方法体内,只能在该方法或条件的作用域内才能使用,退出这写作用域就无法引用。
  • 匿名内部类:
    为了免去给内部类命名,或者只想使用一次,就可以选择使用匿名内部类。

习题:

  1. 内部类可以直接访问(定义它的)外部类的所有成员变量和方法。√
  2. 内部类可以访问外部类的私有成员和方法。√
  3. 外部类可以直接访问内部类的成员。×
  4. 匿名类一定是内部类。√
  5. 匿名类一定是final类。√

6.4 匿名类

  • 匿名类的意义是解决没有显式声明的类想创建对象这一问题。
  • 匿名类是不能有名字的类,它们不能被引用,只能在创建时用 new 语句来声明它们。
  • 匿名类一定是内部类,不可以声明类变量和类方法。(实例变量和实例方法可以声明)?
  • 匿名类不可以是抽象类,抽象类不可以创建对象。
  • 和类有关的匿名类不可以额外实现某个指定的接口。
  • 和接⼝有关的匿名类不可以是抽象类。
  • 匿名类类不可以有static成员变量,但可以使⽤接⼝中的静态常量

参考:链接1
匿名类结构
匿名类继承一个父类:

//以下实例创建的匿名类继承了 Polygon 父类:
class Polygon {
   public void display() {
      System.out.println("在 Polygon 类内部");
   }
}

class AnonymousDemo {
   public void createClass() {
      // 创建的匿名类继承了 Polygon 类
      Polygon p1 = new Polygon() {
         public void display() {
            System.out.println("在匿名类内部。");
         }
      };
      p1.display();
   }
}

class Main {
   public static void main(String[] args) {
       AnonymousDemo an = new AnonymousDemo();
       an.createClass();
   }
}

实现结果:在匿名类内部。
匿名类实现一个接口:

//以下实例创建的匿名类实现了 Polygon 接口:
interface Polygon {
   public void display();
}

class AnonymousDemo {
   public void createClass() {

      // 匿名类实现一个接口
      Polygon p1 = new Polygon() {
         public void display() {
            System.out.println("在匿名类内部。");
         }
      };
      p1.display();
   }
}

class Main {
   public static void main(String[] args) {
      AnonymousDemo an = new AnonymousDemo();
      an.createClass();
   }
}
  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值