抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
1.因为抽象类不能实例化对象,所以必须要有子类来实现它之后才能使用。这样就可以把一些具有相同属性和方法的组件进行抽象,这样更有利于代码和程序的维护。
比如本科和研究生可以抽象成学生,他们有相同的属性和方法。这样当你对其中某个类进行修改时会受到父类的限制,这样就会提醒开发人员有些东西不能进行随意修改,这样可以对比较重要的东西进行统一的限制,也算是一种保护,对维护会有很大的帮助。
2.当又有一个具有相似的组件产生时,只需要实现该抽象类就可以获得该抽象类的那些属性和方法。
比如学校又新产生了专科生这类学生,那么专科生直接继承学生,然后对自己特有的属性和方法进行补充即可。这样对于代码的重用也是很好的体现。
所以,Java中抽象类对于代码的维护和重用有很好的帮助,也是Java面向对象的一个重要体现。
抽象方法
:就 是以abstract修饰的方法,这种方法是不完整的;仅有声明而没有方法体。
abstract void f();
抽象类
:包含一个或多个抽象方法称为抽象类。抽象类不能被实例化(be instantiated),但可以实例化非抽象子类。
抽象类的实现
abstract class A{
public void fun(){
System.out.println("存在方法体的方法");
public abstract void print();
抽象类的使用
直接实例化抽象类的对象(错误)
abstract class A{
public void fun(){
System.out.println("存在方法体的方法");
public abstract void print();
public class TestDemo {
public static void main(String[] args) {
A a = new A();
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Cannot instantiate the type A
at com.wz.abstractdemo.TestDemo.main(TestDemo.java:14)
从上可知,A是抽象的,无法直接进行实例化操作。为什么不能直接实例化呢?当一个类实例化之后,就意味着这个对象可以调用类中的属性或者放过了,但在抽象类里存在抽象方法,而抽象方法没有方法体,没有方法体就无法进行调用。既然无法进行方法调用的话,又怎么去产生实例化对象呢。
抽象类的使用原则如下
(1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
(4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。);
要实现抽象方法就得让子类去继承抽象类,所以就得了解继承,我前面写了一篇关于继承的大家可以看下我写的关于继承的博客http://www.cnblogs.com/yangliguo/p/7481550.html
abstract class A{
public void fun(){
System.out.println("存在方法体的方法");
public abstract void print();
class B extends A{
@Override
public void print() {
System.out.println("Hello World !");
public class TestDemo {
public static void main(String[] args) {
A a = new B();
a.fun();
运行结果:
Hello World !
现在就可以清楚的发现:
(1)抽象类继承子类里面有明确的方法覆写要求,而普通类可以有选择性的来决定是否需要覆写;
(2)抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样;
(3)普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。
虽然一个类的子类可以去继承任意的一个普通类,可是从开发的实际要求来讲,普通类尽量不要去继承另外一个普通类,而是去继承抽象类。
抽象类的使用限制
(1)抽象类中有构造方法么?
由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。
并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。
abstract class A{
public A(){
System.out.println("*****A类构造方法*****");
public abstract void print();
class B extends A{
public B(){
System.out.println("*****B类构造方法*****");
@Override
public void print() {
System.out.println("Hello World !");
public class TestDemo {
public static void main(String[] args) {
A a = new B();
执行结果:
*****A类构造方法*****
*****B类构造方法*****
(2)抽象类可以用final声明么?
不能,因为抽象类必须有子类,而final定义的类不能有子类;
(3)抽象类能否使用static声明?
关于外部抽象类的范例:
static abstract class A{
public abstract void print();
class B extends A{
public void print(){
System.out.println("**********");
public class TestDemo {
public static void main(String[] args) {
A a = new B();
a.print();
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Illegal modifier for the class A
at com.wz.abstractdemo.A.<init>(TestDemo.java:2)
at com.wz.abstractdemo.B.<init>(TestDemo.java:8)
at com.wz.abstractdemo.TestDemo.main(TestDemo.java:17)
关于内部抽象类:
abstract class A{
static abstract class B{
public abstract void print();
class C extends A.B{
public void print(){
System.out.println("**********");
public class TestDemo {
public static void main(String[] args) {
A.B ab = new C();
ab.print();
执行结果:
(4)可以直接调用抽象类中用static声明的方法么?
任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。
(5)有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。
abstract class A{
public abstract void print();
private static class B extends A{
public void print(){
System.out.println("Hello World !");
public static A getInstance(){
return new B();
public class TestDemo {
public static void main(String[] args) {
A a = A.getInstance();
a.print();
运行结果:
Hello World !
向上、向下转型(补充)
向上转型:子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口
向下转型:父类引用的对象转换为子类类型称为向下转型。
前者是一个向上转型,Animal dog 引用指向new Dog();子类对象当成父类对象,只能调用父类的成员,如果子类重写了父类的方法就根据这个引用指向调用子类重写的这个方法(这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。
转型需要注意的问题:
向上转型时,父类指向子类引用对象会遗失除与父类对象共有的其他方法,也就是在转型过程中,子类的新有的方法都会遗失掉,在编译时,系统会提供找不到方法的错误。实例如下:
public class Animal {
public void eat(){
System.out.println("animal eatting...");
class Bird extends Animal{
public void eat(){
System.out.println("bird eatting...");
public void fly(){
System.out.println("bird flying...");
class Main{
public static void main(String[] args) {
Animal b=new Bird();
b.eat();
b.fly();
在向下转型过程中,分为两种情况:
情况一:如果父类引用的对象如果引用的是指向的子类对象,那么在向下转型的过程中是安全的。也就是编译是不会出错误的。
情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。实例如下:
public class Girl {
public void smile(){
System.out.println("girl smile()...");
class MMGirl extends Girl{
@Override
public void smile() {
System.out.println("MMirl smile sounds sweet...");
public void c(){
System.out.println("MMirl c()...");
class Main{
public static void main(String[] args) {
Girl g1=new MMGirl();
g1.smile();
MMGirl mmg=(MMGirl)g1;
mmg.smile();
mmg.c();
Girl g2=new Girl();