java语言,声明类时格式为: abstract class Db{} 说明Db类为抽象类。抽象方法是说没有方法的实现(方法体)此方法为抽象方法,只有抽象类和接口中才可以有抽象方法。简而言之,含有抽象方法的类一定是抽象类;关键字是abstract
抽象类本质使用规则1.从类的组成上看其是抽象方法和非抽象方法的集合,还有属性(常量)。
2.从设计的角度来看,实际上抽象类定义了一套规范(抽象方法)。(规范)
下面逐条解释:
规则一抽象类必须被继承,抽象方法必须被重写。
规则二抽象类中的抽象方法只需声明,无需实现,没有方法体。
在Java中抽象类实际上是一种规范,一般在抽象类中声明方法不直接提供方法体(当然也可以提供),而是通过其子类去重写其抽象方法:
package day_12_01.abs; public abstract class A { //报错,不能定义抽象属性 // abstract int a; //可以声明属性 private int a; //可以声明一个普通方法 public void a(){ } //报错,因为抽象方法不能有方法体,即不能去实现 // public abstract void aa(){ // // } //抽象方法正确格式 public abstract void aa(); //抽象方法不能是私有的private // private abstract void bb(); } //没有重写父类的抽象方法aa(),报错 //class B extends A{ // //}
注意
规则三抽象方法不能是私有的private,因为一旦私有,子类就不能重写了,但这违背了抽象方法必须被重写的原则。
抽象类不能被实例化,抽象类不一定要包含抽象方法,而定义抽象方法的类必须是抽象类。
首先,抽象类不能被实例化,当一个类实例化对象后,这个对象就可以调用类中的属性或者方法了,但在抽象类有抽象方法(没有方法体),无法调用。自相矛盾,所以无法实例化。比如,我想实例化上例中的抽象类A:
class TestA{ public static void main(String[] args) { //报错 // A a = new A(); } }
抽象类不一定有抽象方法,这点显而易见,但是意义不大:
//一个空的抽象类 abstract class AA{ }
然后,定义抽象方法的类必须是抽象类,这点也很好理解,一个普通的类是可以被实例化的,如果这个普通类存在抽象方法,那我是不是就可以通过对象去调用呢?当然不能。
package day_12_01.abs; //报错,因为抽象方法必须声明在抽象类中 //public class B { // public abstract void b(); //}规则四
抽象类包含的抽象方法必须在其子类中被实现,否则该子类也必须是抽象类。
还拿上述代码做例子,如果我声明了一个类B,继承于A,那B就必须重写A中的抽象方法,否则报错(因为普通类中不能有抽象方法),解决方式一:重写父类抽象方法;解决方式二:将B声明为abstract:
//解决方式一:重写父类抽象方法 class B extends A{ @Override public void aa() { } } //解决方式二:将B声明为abstract abstract class Bb extends A{ }规则五
抽象类可以有构造方法供子类实例化对象。
这点很好理解,因为首先可以确定的是,Java中所有的类都有构造方法,即使你是抽象类,虽然我们没写,但其实系统已经默认给我们提供了一个无参的空构造器,例如下面我显示化的在抽象类中声明一个构造方法:
package day_12_01.abs; public abstract class Ab { public Ab(){ System.out.println("Abs......"); } } class Abs extends Ab{ } class Test{ public static void main(String[] args) { Abs abs = new Abs(); } }
运行结果:
证明我们在创建子类实例化对象时,父类的构造器也可实现(哪怕父类是抽象类)
抽象类不能直接实例化使用,一般用的是抽象类的子类。
抽象类不能去实例化对象,那如果我想用其中的一些非抽象方法呢,比如静态方法,比如普通方法呢或者是属性?
我们可以通过继承关系,去创建其子类的对象,形如:
A a = new B(); //其中A是父类,B是子类
package day_12_01.abs; public abstract class TT { String some = "hello"; public static void talk() { System.out.println("talk..."); } public void say() { System.out.println("say..." + some); } } class FF extends TT{ } class FFTest{ public static void main(String[] args) { TT.talk(); TT f = new FF(); f.say(); } }
运行结果:
如果子类重写了父类的非抽象方法,那实际调用的就是子类重写后的。通过子类去调用父类的方法,即通过父类去new一个子类的对象,这实际上也是多态性的一种体现。当然了,抽象类中的静态方法是可以直接调用的(除非是私有的),实际上对任何类都一样。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)