Java 关键字之abstract用法

本篇文章主要分析abstract修饰符的用法,abstract和接口的比较以及常见的面试题。

文章部分内容来源于网络,转载请标明出处,并标记作者ID:Soinice

abstract 简介

字面意思抽象,abstract一般用来修饰类和方法

抽象就是把一个对象分析出各个属性, 来替代表达的手法 。
抽 就是抽离;象 ,表象。表示出来的部分。

简单地说:“抽象只从正确的角度,透露对象的某些相关细节。

在面向对象编程理论中,抽象涉及到定义抽象对象的语言基础,它到底如何工作、如何获取和改变状态,并与系统中的其他对象进行“交流”。

抽象在任何编程语言中的许多方面起作用。从创建子程序到定义接口来,生成低级语言调用,例如设计模式。

在《Java编程思想》第9章 接口中 有这么一段话:

  “为此,Java提供了一种叫抽象方法的机制,这种方法是不完整的,仅有声明而没有方法体。

        包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须限定为抽象的。(否则,编译器会报错)

abstract 用法

修饰方法

abstract修饰方法会使得这个方法变成抽象方法,也就是只有声明,而没有实现,需要子类重写。
注意:

  • 有抽象方法的类一定是抽象类,但是抽象类不一定有抽象方法。
  • 父类是抽象类,其中有抽象方法,那么子类继承父类,并把父类中的所有抽象方法都实现了,子类才有创建对象实例的能力,否则子类也必须是抽象类。抽象类中可以有构造方法,子类在构造子类对象时需要调用父类(抽象类)的构造方法。
  • 抽象方法不能用private修饰,因为抽象方法必须被子类重写,而private权限对于子类来说是不能访问的,所以就会产生矛盾。
  • 抽象方法也不能用static修饰,如果用static修饰了,那么我们就可以直接通过类名调用了,而抽象方法压根没有主体,没有任何业务逻辑,这样就毫无意义了。

修饰类

abstract修饰类,会使得类变成抽象类,抽象类不能生成实例,但是可以作为对象变量声明的类型,也就是编译时类型。抽象类相当于类的半成品,需要子类继承并覆盖其中的方法。
注意:

  • 抽象类虽然不能实例化,但是有自己的构造方法。
  • 抽象类和接口(interface)有很大的不同之处,接口中不能有实例方法去实现业务逻辑,而抽象类可以有实例方法,并实现业务逻辑。
  • 抽象类不能被final修饰,因为被final修饰的类无法被继承,而对于抽象类来说就是需要通过继承去实现抽象方法。

抽象类的多态性

abstract class E{
    // public abstract可以省略
    public abstract void show();
}

然后其它类继承它通常为了实现它里面的方法。

class F extends{
    void show(){
            写具体代码
    }
}

最后在主方法里定义一个父类引用指向子类对象,就会发生多态现象,比如

E e = new F();
e.show();    

实际上调用了子类里面的new()方法。

抽象类的构造方法

public abstract class Car {
	
     Car(){
          System.out.println("抽象方法无参构造函数");
     }
     Car(String a){
          System.out.println("抽象有参构造方法");
     }  
      
     public void mothod1(){
          System.out.println(this.getClass());
          System.out.println("抽象类的实例方法");
     }
	
     public abstract void mothod2();
	
}


/**
 * 自行车
 */
class Bicycle extends Car{
	
     Bicycle(){
      System.out.println("子类无参构造函数");
     }
	
     @Override
     public void mothod2() {
        //需要覆写抽象方法mothod2
     }
}


/**另一个包的测试类**/
public class Test {

     public static void main(String[] args) {
          Bicycle b = new Bicycle();
          b.mothod1();
     }
}

输出:

抽象方法无参构造函数
子类无参构造函数
class com.shaolin.service.impl.Bicycle
抽象类的实例方法

从上面的例子中可以看出:

  • 抽象类是有构造方法的(当然如果我们不写,编译器会自动默认一个无参构造方法)。而且从结果来看,和普通的继承类一样,在new 一个子类对象时会优先调用父类(这里指的是抽象类Car)的构造器初始化,然后再调用子类的构造器。至此相信大家都会有这样一个疑问,为什么抽象方法不能实例化却有构造器呢? 对于这个问题网上也中说纷纭,没有确定答案。
    我是这样想的:既然它也属于继承的范畴,那么当子类创建对象时必然要优先初始化父类的属性变量和实例方法,不然子类怎么继承和调用呢?而它本身不能实例化,因为它本身就是不确定的一个对象,如果它能被实例化,那么我们通过它的对象来调用它本身的抽象方法是不是有问题。所以不能实例化有在情理之中。因此大家只要记住这个规定就行。

  • 对于抽象类中的非statci(静态)和非abstract(抽象)方法中的this关键字(静态方法中不能有关键字this,因为static方法可以直接由类名调用,this指代对象,没有实例化就没有对象,所以在static方法中不使用this)代表的是它的继承类,而非抽象类本身,这个好理解,因为抽象类本身不能被实例化。如果有多个继承类,谁调用this就代表谁。

abstract 和接口的区别

  1. 抽象类中可以有普通成员变量,接口中没有普通成员变量。
  2. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以是任意的,但是接口中定义的变量只是public static final类型,并且默认为public static final类型。
  3. 抽象类可以有构造方法,接口中不能有构造方法。
  4. 抽象类中可以包含静态方法,接口中不能有静态方法。这里注意,静态方法不要去重写,其次这里的静态方法一定要有具体实现,不能是抽象的。Java8中允许接口中包含静态方法了,可以用接口直接调用。
  5. 抽象类中抽象方法的访问类型可以是public,protected,但是接口中的抽象方法只能是public类型的,并且默认为public abstract类型的。
  6. 一个类可以实现多个接口,但是只能继承一个抽象类。

关于abstract的一些面试题

基本上上面的记录都能回答这10个问题

  • 抽象类中可以有main方法。

  • 可以用抽象类来实现接口,这个时候就不需要实现接口的所有方法了。

总结

抽象类有什么好处呢?

  • 由于抽象类不能被实例化,最大的好处就是通过方法的覆盖来实现多态的属性。也就是运行期绑定

  • 抽象类将事物的共性的东西提取出来,由子类继承去实现,代码易扩展、易维护。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章