类和对象(5)——抽象类和接口

打印 上一主题 下一主题

主题 1603|帖子 1603|积分 4809

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目次
1. 抽象类
1.1 抽象类的概念
1.2 抽象类语法:abstract关键字
1.3 抽象类的特性
1.4 抽象类的作用
2. 接口
2.1 接口的概念
2.2 接口语法:interface关键字
2.3 接口的实现:implements关键字
2.4 接口的特性
2.5 实现多个接口
2.6 接口间的继续
2.7 接口的多态性
2.8 再谈instanceof
2.8.1 检查接口的实现
2.8.2 范例可见性问题
2.8.3 易混淆的可见性
3. 抽象类与接口的区别


1. 抽象类

1.1 抽象类的概念

在面向对象的概念中,全部的对象都是通过类来描绘的;但是反过来,并不是全部的类都是用来描绘对象的,如果 一个类中没有包罗足够的信息来描绘一个具体的对象,这样的类就是抽象类
   

  • 抽象类是一种不能被实例化,只能用作其他类的父类的类。它通常用于界说一组具有共同特征和行为的子类的底子框架,这些共同特征和行为以抽象方法的形式呈现,子类必要提供这些抽象方法的具体实现。
  

1.2 抽象类语法:abstract关键字

那么在java语言中,抽象类要如何表现呢?
java提供了一个abstract关键字,被该关键字修饰的类就是抽象类。
   抽象类的语法:
  (其他修饰词)  abstract  class 抽象类名{
          ……
  }
  abstract除了可以修饰类,还可以修饰成员方法使其成为抽象方法。必要注意的是,抽象方法只能存在于抽象类当中
   抽象方法的语法:
  (其他修饰词)  abstract  class 抽象类名{
          ……
          (其他修饰词)  abstract  返回值范例  抽象方法名 (参数表)  //抽象方法无具体实现
          ……
  }
  比方:
  1. public abstract class Animal {
  2.     private String name;
  3.     private int age;
  4.     //抽象方法
  5.     abstract public void eat();
  6. }
复制代码
1.3 抽象类的特性

抽象类具有很多的特性和使用要求,我在下面逐一枚举出来。
   1. 抽象类不能被直接实例化成对象。
  以上面抽象类Animal为例:


着实这样的要求也很好理解,由于抽象类的产生就不是为了形貌对象的,它也没有包罗足够的信息来描绘一个具体的对象,必须由它的非抽象子类来实例化对象。

   2. 抽象类被继续后,其子类要重写父类中的抽象方法;否则子类也必须设为抽象类,被abstract修饰。
  子类Dog没有重写抽象方法,且没有设为抽象类而报错:
  1. package demo3;    //包名:demo3
  2. //抽象父类Animal
  3. public abstract class Animal {
  4.     public String name;
  5.     public int age;
  6.     //抽象方法
  7.     abstract public void eat();
  8. }
  9. //Dog类继承自抽象类
  10. public class Dog extends Animal{
  11.     public void bark(){
  12.         System.out.println(name+"在汪汪叫");
  13.     }
  14. }
复制代码


   补充:非抽象子类必要重写的抽象方法都来自其直接父类的抽象方法。
  如果有A、B、C三个类,A是B的直接父类,B是C的直接父类;A和B都是抽象类,C是普通类。如果B重写了A中的部门抽象方法,那么C要重写的抽象方法有 A剩下的抽象方法 和 B新增加的抽象方法。
  比方:
  1. ​//抽象类Animal
  2. public abstract class Animal {
  3.     public String name;
  4.     //2个抽象方法
  5.     abstract public void eat();
  6.     abstract public void sleep();
  7. }
  8. //抽象类Dog
  9. public abstract class Dog extends Animal{
  10.     //重写了抽象方法eat()
  11.     public void eat(){
  12.         System.out.println(name+"在吃狗粮");
  13.     }
  14.     //新增1个抽象方法walk()
  15.     abstract public void walk();
  16. }
  17. //普通类 柯基
  18. public class Corgi extends Dog{
  19.     //报错:没有重写抽象方法sleep()和walk()
  20. }
复制代码


这里Dog继续自Animal,所以Dog包罗成员变量name、父类方法eat和sleep 以及自己新增的抽象方法walk。
又由于Dog重写了抽象方法eat,eat方法在Dog类已经不是抽象方法,所以Dog类中只有sleep和walk两个抽象方法。
由于非抽象子类必要重写的抽象方法都来自其直接父类的抽象方法,所以柯基Corgi类必须要重写sleep和walk这两个直接来自Dog类的抽象方法。

   3. 抽象方法不能被private、final和static修饰,由于抽象方法要被子类重写。
  





   4. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量。
  


   5. 抽象类中不一定有抽象方法,但是抽象方法只能存在于抽象类当中。
  无抽象方法的抽象类:

报错·含抽象方法的普通类:



1.4 抽象类的作用

   抽象类自己不能被实例化,要想使用,只能创建该抽象类的子类。 然后让子类重写抽象类中的抽象方法。
  有些同砚可能会说了, 普通的类也可以被继续呀, 普通的方法也可以被重写呀, 为啥非得用抽象类和抽象方法呢?
确实云云. 但是使用抽象类相当于多了一重编译器的校验.
使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类 了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.
很多语法存在的意义都是为了 "预防堕落", 比方我们曾经用过的 final 也是类似. 创建的变量用户不去修改, 不 就相当于常量嘛? 但是加上 final 可以或许在不小心误修改的时候, 让编译器实时提醒我们. 充实利用编译器的校验, 在实际开发中黑白常故意义的

2. 接口

2.1 接口的概念

在现实生活中,接口的例子比比皆是,好比:笔记本上的USB口,电源插座等。
电脑侧面的USB口上,可以插:U盘、鼠标、键盘...全部符合USB协议的装备
电源插座的插孔上,可以插:电脑、电视机、电饭煲...全部符合规范的装备
   通过上述例子可以看出:接口就是公共的行为规范标准。各人在实现时,只要符合规范标准,就可以通用
  我们知道,在编程上我们用类来形貌对象,像电脑、鼠标、U盘这些对象都可以用类来形貌。天然的,我们也会有编程上的接口。
   在Java中,接口可以看成是多个类的公共规范,也是一种引用数据范例。
  
2.2 接口语法:interface关键字

接口的语法格式 与 类的语法格式类似,将 class关键字 换成 interface关键字,就界说了一个接口。
   接口的语法格式:
  (其他限定词)  interface  接口名{
          ……
  }
  比方:写一个图形接口,规范是要实现画图形方法draw。
  1. public interface IShape {
  2.     void draw();    //画一个图形
  3. }
复制代码
  注意:
  

  • 接口的定名采用大驼峰定名法。
  • 接口的定名一般以大写字母 I 开头,它的后一个字母也要大写。
  
2.3 接口的实现:implements关键字

接口不能直接使用,必须要有一个"实现类"来"实现"该接口。而实现指的是:重写接口中的全部抽象方法。(在接口中界说的方法都是抽象方法)
在java中,提供一个关键字implements来让我们完成对接口的实现
   实现的语法:
  (其他限定词) class 类名 implements 接口名{
          ……
          //重写的接口方法
  }
  比方:
  1. //接口public interface IShape {
  2.     void draw();    //画一个图形
  3. }//实现类public class Flower implements IShape{    @Override    public void draw() {        System.out.println("画一朵花……");    }}//测试public class Test {    public static void main(String[] args) {        IShape iShape = new Flower();//向上转型        iShape.draw();    }}
复制代码

可以看到,实现了接口,可以通过向上转型的方式来调用接口函数,这是接口多态性的一种体现。

2.4 接口的特性

   1. 与抽象类一样,接口虽是一种引用范例,但是不能直接new接口的对象。
  比方:



   2. 接口中的成员变量都是被“ public static final ”修饰的。
  也就是说,接口中的成员变量是一种静态全局常量。无论是无修饰(default),照旧显式用public修饰、static修饰或final修饰,它们最终都是由“ public static final ”共同修饰。
以下面的USB接口为例:
  1. public interface USB {
  2.     double brand = 10;
  3. }
复制代码



   3. 接口中的方法都是由“ public abstract ”修饰。
  无论是无修饰(default),照旧显式用public修饰或abstract修饰,接口方法都是由“ public abstract ”共同修饰。也就是说接口方法都是公共的抽象方法,必须要求实现类举行方法重写,这体现了接口作为公共规范的作用
比方:
// 接口IShape

// Flower类


Flower类没有重写IShape接口的draw方法,由于接口方法都是抽象的,所以会报错。
   补充:如果实现类没有重写接口的全部抽象方法,那么该实现类要设为抽象类
  
   4. 由于接口的变量和方法都有固定的修饰符修饰,所以不能用其他修饰符 修饰接口的变量和方法。(好比private、protected)
  错误例子:


   补充:接口的变量和方法都有默认修饰符,一般发起接口的变量和方法前面都不写任何修饰符
  
   5. 接口中不能有静态代码块、动态代码块 和 构造方法。
  静态代码块一般用来初始化静态变量,动态代码块和构造方法一般用来初始化成员变量,但是接口中的变量都是常量,不能修改。
错误例子:
  1. public interface USB {
  2.     int BRAND = 10;
  3.     static {
  4.          //静态代码块
  5.     }
  6.     {
  7.          //实例代码块
  8.     }
  9.     USB(int brand){
  10.         BRAND = brand;
  11.     }
  12. }
复制代码


   6. 实现类重写接口方法时,重写的方法的包访问权限不能比接口方法的权限要低。即:不能是无修饰词(default)、不能是protected、不能是private。
  比方:


【补充:着实 实现类的重写方法的访问权限在一种情况可以是无修饰词(default)的,这种情况我在第8点说】

   7(小知识). 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class。
  
   8(拓展). 从Java8版本开始,接口中可以界说default方法(默认方法)。它允许在接口中为方法提供默认的实现。
  default方法在接口中的界说方式:
  

  • 表现使用default关键字:在接口的方法签名前使用default关键字来界说一个默认方法。比方,default void methodName() {...}。
  • 包罗方法体:与接口中的抽象方法不同,默认方法是具体的方法实现,必要在接口中给出方法的具体代码逻辑。
  【注意】: 接口方法被default修饰后,就不能再被final和static修饰。
  比方:
  1. //图形·接口
  2. public interface IShape {
  3.     //抽象方法
  4.     void draw1();
  5.     //默认方法
  6.     default  void draw2(){
  7.         System.out.println("画两次图形");
  8.     }
  9. }
  10. //圆形·类 :只重写抽象方法
  11. public class Circle implements IShape{
  12.     @Override
  13.     public void draw1() {
  14.         System.out.println("画一个圆……");
  15.     }
  16. }
  17. //花形·类:抽象方法和默认方法都重写了
  18. public class Flower implements IShape{
  19.     @Override
  20.     public void draw1() {
  21.         System.out.println("画一朵花……");
  22.     }
  23.     @Override
  24.     public void draw2() {
  25.         System.out.println("画两朵花");
  26.     }
  27. }
  28. public class Test {
  29.     public static void main(String[] args) {
  30.         Circle circle = new Circle();
  31.         circle.draw1();
  32.         circle.draw2();    //会使用接口的默认方法
  33.         System.out.println("============================");
  34.         Flower flower = new Flower();
  35.         flower.draw1();
  36.         flower.draw2();
  37.     }
  38. }
复制代码

【这里的第8点特性属于拓展内容,相识即可】


2.5 实现多个接口

java中没有多继续,即一个子类不能继续自多个父类,但是一个类可以实现多个接口。
   语法格式:(全部的接口都跟在implements的背面,每个接口之间用逗号隔开)
  【无继续】
    class 实现类 implements 接口1,接口2,……,接口K{
            ……  //实现类的成员
    }
  【有继续】(只能有一个父类) (“继续extends”要在“实现implements”前面)
    class 实现类 extends 父类名称 implements 接口1,接口2,……,接口K{
            ……  //实现类的成员
    }
  下面演示如何用接口和继续来表现企鹅类:
先有父类Animal:
  1. abstract public class Animal {
  2.     protected String name;
  3.    
  4.     public Animal(String name){
  5.          this.name = name;
  6.     }
  7. }
复制代码
别的我们再提供一组接口, 分别表现 "会飞的", "会跑的", "会游泳的":
  1. interface IFlying {
  2.     void fly();
  3. }
  4. interface IRunning {
  5.     void run();
  6. }
  7. interface ISwimming {
  8.     void swim();
  9. }
复制代码
末了我们创建具体的动物——企鹅类(企鹅既能在路上走,也能在水中游)
  1. public class Penguin extends Animal implements IRunning,ISwimming{
  2.     public Penguin(String name) {
  3.         super(name);
  4.     }
  5.     @Override
  6.     public void run() {
  7.         System.out.println(name+"用两只脚走路");
  8.     }
  9.     @Override
  10.     public void swim() {
  11.         System.out.println(name+"用两只翅膀游泳");
  12.     }
  13. }
复制代码
  tips:在IDEA中使用 ctrl + i 可快速实现接口。
  

2.6 接口间的继续

类与类之间可以有继续关系,那接口与接口之间可以有继续关系吗?
   接口与接口之间可以有继续关系,而且接口可以多继续,即一个接口可以继续自多个接口。
    语法格式:(继续语法是extends,每个父接口之间用逗号隔开)
  interface 子接口 extends 父接口1,父接口2,……,父接口k{
          ……
  }
  田鸡是两栖动物,我们用接口间的继续可以这样表现:
  1. interface IRunning {
  2.     void run();
  3. }
  4. interface ISwimming {
  5.     void swim();
  6. }
  7. // 两栖的动物:既能跑, 也能游
  8. interface IAmphibious extends IRunning, ISwimming {
  9. }
  10. class Frog implements IAmphibious {
  11.     ...
  12. }
复制代码

2.7 接口的多态性

   当实现类实现了接口,那么它就可以向接口范例举行向上转型。这体现了接口的多态性。
  接口不仅仅是一种规范标准,它照旧一种引用范例,这样的计划提高了代码的可重复性。
   【实现多个接口】
  实现类实现了多个接口,那么被实现的接口都可以吸收实现类的向上转型。
  比方:
  1. //接口
  2. public interface ISwimming {
  3.     void swim();
  4. }
  5. public interface IRunning {
  6.     void run();
  7. }
  8. //实现类
  9. public class Penguin implements ISwimming,IRunning{
  10.     @Override
  11.     public void swim() {
  12.         System.out.println("企鹅游泳");
  13.     }
  14.     @Override
  15.     public void run() {
  16.         System.out.println("企鹅走路");
  17.     }
  18. }
  19. public class Dog implements IRunning{
  20.     @Override
  21.     public void run() {
  22.         System.out.println("狗在奔跑");
  23.     }
  24. }
  25. //多态方法
  26. public class Test {
  27.     public static void swim(ISwimming iSwimming){   //ISwimming接口类型作为多态类型参数
  28.         iSwimming.swim();   //方法会根据动态绑定来使用
  29.     }
  30.     public static void run(IRunning iRunning){      //IRunning接口类型作为多态类型参数
  31.         iRunning.run();
  32.     }
  33.     public static void main(String[] args) {
  34.         Penguin penguin = new Penguin();
  35.         swim(penguin);     //向上转型传参
  36.         run(penguin);
  37.         System.out.println("==============");
  38.         Dog dog = new Dog();
  39.         run(dog);
  40.     }
  41. }
复制代码

这里的Penguin类实现了ISwimming接口和IRunning接口,所以swim方法和run方法可以完成对penguin的向上转型。

   【接口间的继续】
  如果子接口继续自父接口,而实现类“直接实现”的是子接口,那么父接口也可以吸收实现类的向上转型。
  比方:
  1. //IAmphibious接口继承自上面的ISwimming、IRunning接口
  2. public interface IAmphibious extends ISwimming,IRunning{
  3. }
  4. //Penguin类直接实现IAmphibious接口
  5. public class Penguin implements IAmphibious{
  6.     @Override
  7.     public void swim() {
  8.         System.out.println("企鹅游泳");
  9.     }
  10.     @Override
  11.     public void run() {
  12.         System.out.println("企鹅走路");
  13.     }
  14. }
  15. public class Test {
  16.     public static void swim(ISwimming iSwimming){   //ISwimming接口类型作为多态类型参数
  17.         iSwimming.swim();   
  18.     }
  19.     public static void run(IRunning iRunning){      //IRunning接口类型作为多态类型参数
  20.         iRunning.run();
  21.     }
  22.     public static void main(String[] args) {
  23.         Penguin penguin = new Penguin();
  24.         swim(penguin);     
  25.         run(penguin);
  26.     }
  27. }
复制代码



  • Penguin类实现了Imphibious接口,所以Penguin可以向Imphibious转型。
  • 而Imphibious继续自ISwimming接口和IRunning接口,所以Imphibious可以向ISwimming接口和IRunning接口转型。
  • 于是乎Penguin可以向ISwimming接口和IRunning接口向上转型

   【注意】
  如果子接口继续自父接口,实现类直接实现的也是这个父接口,那么该实现类不能向子接口举行向上转型。
  错误例子:
  1. //父接口
  2. public interface IRunning {
  3.     void run();
  4. }
  5. //子接口:表示爬行类的动物
  6. public interface ICreeping extends IRunning{
  7. }
  8. //实现类:蜥蜴
  9. public class Lizard implements IRunning{
  10.     @Override
  11.     public void run() {
  12.         System.out.println("蜥蜴在快速爬行");
  13.     }
  14. }
  15. //用子接口ICreeping接收实现类Lizard
  16. public class Test {
  17.     public static void run(ICreeping iCreeping){      
  18.         iCreeping.run();
  19.     }
  20.     public static void main(String[] args) {
  21.         Lizard lizard = new Lizard();
  22.         run(lizard);        //报错:Lizard类型与ICreeping类型不兼容
  23.     }
  24. }
复制代码



接口多态性与继续多态性的对比:



2.8 再谈instanceof

2.8.1 检查接口的实现

我在《类和对象(4)——多态》中解说过instanceof关键字,当时说过“该关键字不仅能判断类,还能判断接口”。但当时还没学到接口,如今让我们看看instanceof对于接口的作用。
   instanceof的作用:(对象  instanceof  类名/接口名)
  

  • 对于类:检查对象是否是指定范例的实例,或该范例的子类实例。
  • 对于接口:检查对象是否实现了指定接口,或该接口的父接口。
  为什么instanceof检查类的时候,可以检查其子类,而在检查接口的时候,却是可以检查其父接口呢?
这就不得不说一下instanceof检查的实际用途了:
   类和instanceof的用途:确保向下转型的安全,从而让子类实例变量吸收向下转型后的父类实例变量,使用子类特有的功能。
  接口和instanceof的用途:确保对象具有某类多态行为,从而调用该多态方法。
  类的举例息争析:
  1. abstract public class Animal {
  2.     public String name;
  3.     public Animal(String name){
  4.         this.name = name;
  5.     }
  6. }
  7. public class Dog extends Animal{
  8.     public Dog(String name) {
  9.         super(name);
  10.     }
  11.     public void eat(){
  12.         System.out.println(super.name+"在吃狗粮");
  13.     }
  14. }
  15. public class Corge extends Dog{
  16.     public Corge(String name) {
  17.         super(name);
  18.     }
  19.     public void eat(){
  20.         System.out.println(name+"在吃科技合成肉");
  21.     }
  22. }
  23. public class Test {
  24.     public static void main(String[] args) {
  25.         Animal animal1 = new Dog("小狗");
  26.         if (animal1 instanceof Dog){    //检查为Dog类的实例
  27.             Dog dog = (Dog) animal1;
  28.             dog.eat();
  29.         }
  30.         Animal animal2 = new Corge("小柯基");
  31.         if(animal2 instanceof Dog){     //检查为Dog类的子类实例
  32.             Dog dog = (Dog) animal2;
  33.             dog.eat();
  34.         }
  35.     }
  36. }
复制代码



  • Dog类和Corge类都有自己特有的eat方法。
  • 在animal1中,由于对象的本质是Dog类的实例,故可以安全地将animal1向下转型成Dog类。
  • 在animal2中,虽然对象的本质是Corge类的实例,但由于Corge类是Dog类的子类(即Corge类可以向上转型成Dog类),所以它也可以安全地将animal2向下转型成Dog类。
  • 这就解释了:为什么instanceof能检查指定范例的子类。
接口的举例息争析:
  1. //父接口
  2. public interface IRunning {
  3.     void run();
  4. }
  5. public interface ISwimming {
  6.     void swim();
  7. }
  8. //子接口
  9. public interface IAmphibious extends ISwimming,IRunning{
  10. }
  11. //实现类
  12. public class Penguin extends Animal implements IAmphibious{
  13.     @Override
  14.     public void swim() {
  15.         System.out.println("企鹅游泳");
  16.     }
  17.     @Override
  18.     public void run() {
  19.         System.out.println("企鹅走路");
  20.     }
  21. }
  22. //多态方法
  23. public class Test {
  24.     public static void run(IRunning iRunning){
  25.         iRunning.run();
  26.     }
  27.     public static void main(String[] args) {
  28.         Animal animal = new Penguin();  //向上转型
  29.         if(animal instanceof IAmphibious){   检查到指定接口的父接口的run行为
  30.             run( (IAmphibious)animal );         //此时调用的是Test类中的多态方法run
  31.             //或写成((IAmphibious)animal).run();  此时调用的是自己的重写方法run
  32.         }
  33.         if(animal instanceof IRunning){      检查指定接口
  34.             run((IRunning) animal);
  35.             //或写成((IRunning)animal).run();
  36.         }
  37.     }
  38. }
复制代码



  • 子接口继续自多个父接口,实现类直接实现子接口 就相当于是 把全部父接口的行为都实现了一遍,那天然可以使用 以父接口范例为参数范例的多态方法。
  • 这解释了:为什么instanceof能检查指定接口的父接口。

小结:



2.8.2 范例可见性问题

如果我们将上面接口例子中Test类(含多态方法的那个)修改成下面这样会发生什么:


可以发现,我们把强制范例转换用的“(IAmphibious)”去掉后居然报错了。这是编译时范例对成员可见性的限定惹的祸。

要明白 “编译时范例对成员可见性的限定”,我们必需先相识编译时范例和运行时范例的概念。
   编译时范例(也称 声明范例)
  

  • 变量在代码中声明的范例。(如" Parent parent;",此时实例变量parent的数据范例Parent就是编译时范例)(编译时范例也包罗底子范例,如int、double)
  • 编译器仅根据此范例检查可访问的成员变量和方法。
  运行时范例(也称 实际范例)
  

  • 对象实际所属的范例。(如“ new Child() ”)
  • 运行时动态决定,但编译时不可见。
  当用编译时范例的变量 访问 运行时范例的特有成员时,编译器检查发现该声明范例不具有访问特有成员的本领,直接触发了编译错误。这就是编译时范例对可见性的限定。
   

  • 强制转换的作用
    强制转换的本质是 告诉编译器,请按强转范例检查成员。编译器接受新的编译时范例,从而允许访问该范例界说的成员。
  • 运行时验证
    强制转换可能在运行时失败(如 强转范例 与 对象实际范例 不符),因此需配合 instanceof 提前检查范例安全。
  
2.8.3 易混淆的可见性

上述发生的编译错误属于范例可见性的问题,而不是权限的问题。
   成员可见性:
  

  • 在java中,权限指的就是各种访问修饰符
  • 成员可见性的控制机制是访问修饰符(好比public、protected),为每个成员变量和方法赋予权限。
  


   类可见性:
  

  • 类可见性的控制机制也是访问修饰符,为类赋予访问权限。
  • 成员可见性是 成员变量和成员方法 被访问修饰符修饰,共有4种权限;类可见性是  被访问修饰符修饰,顶级类只有public类或默认类(default)2种
  • 类的可见性是成员可见性的 条件。(如果顶级类是默认类,且内部全部成员都是public修饰的,那么不是同一个包的类就无法访问该顶级类及其全部成员。)
  错误例子:
在包test1中有默认类Demo:

当我们在包test2中实验使用Demo会报错:




   包可见性:
  

  • 包可见性 = default 权限 = 包访问权限 = 仅包内可见。
  • 包可见性 包罗于 成员可见性和类可见性当中。(包可见性是权限中的一种具体范例)
  
成员可见性和类的可见性通过访问修饰符界说,具体规则如下:


   最终总结:
  

  • 类可见性 和 成员可见性属于访问权限控制的同一维度(层级不同),且 类可见性是成员可见性的条件
  • 包可见性是访问权限控制中的一种具体范例(默认修饰符),属于成员可见性和类可见性的一部门。
  • 范例可见性是独立于访问控制的另一维度,属于编译时范例系统的限定。
  
3. 抽象类与接口的区别

焦点区别: 抽象类中可以包罗普通方法和普通字段,这样的普通方法和字段可以被子类直接使用(不必重写),而接口中不能包罗普通方法(但是可以包罗default方法),子类必须重写全部的抽象方法。
下面的表格是抽象类和接口不同的地方:

   抽象类和接口的类似之处:
  

  • 可以没有任何成员。(此时的接口被称作空接口或标志接口)
  • 抽象方法不能被private、static、final修饰。
  • 子类/实现类 重写方法的包访问权限不能更低。
  • 子类/实现类 没有重写完全部的抽象方法时,必须设置为抽象类。
  • 字节码文件的后缀都是.class。
  
本期分享完毕,感谢各人的支持Thanks♪(・ω・)ノ


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表