当知道一个类的子类将不同的实现某个方法时,把该类声明为抽象类很有用,可以共用相同的父类方法,不必再定义。
抽象类和抽象方法的关系:含有抽象方法的类一定是抽象类,抽象类里不一定含有抽象方法。
抽象类存在的意义是用来被继承的。 一个类继承了一个抽象类,必须实现抽象类里面所有的抽象方法,否则,此类也是抽象类。 
abstract修饰符用来修饰类和成员方法
1:用abstract修饰的类表示抽象类,抽象类位于继承树的抽象层, 抽象类不能被实例化。
2:用abstract修饰的方法表示抽象方法, 抽象方法没有方法体。 抽象方法用来描述系统具有什么功能,但不提供具体的实现。 
abstract 规则:
1:抽象类可以没有抽象方法,但是有抽象方法的类必须定义为抽象类,如果一个子类继承一个抽象类,子类没有实现父类的所有抽象方法,那么子类也要定义为抽象类,否则的话编译会出错的。
2:抽象类没有构造方法,也没有抽象静态方法。但是可以有非抽象的构造方法
3:抽象类不能被实例化,但是可以创建一个引用变量,类型是一个抽象类,并让它引用非抽象类的子类的一个实例
4:不能用final 修饰符修饰
 
Q:java里面有抽象类么?和接口的区别是什么?
A:java中有抽象类,用关键字abstract修饰。
以下是我对这个问题的看法。
首先,从语法上讲,抽象类是一个类,根据java的单继承体系。如果它有子类,那么它的子类只能继承它。
java允许实现多个接口。所以一个类可以实现多个接口
抽象类里面可以定义各种类型和访问权限的变量(就像普通类一样),也可以定义各种访问权限的方法(就像普通类一样)。
但是接口不可以。在接口里面定义的方法默认就是public abstract的,变量默认就是public static final的。(不管你有没有加权限控制符,不加,默认就是这些权限;加错了,权限缩小了,那么就会报错)
其次,从意义上讲,如果继承一个抽象类,那么抽象类和它的子类就有父子关系,即有类的层次关系(这关系到类的设计问题)。
接口,在我看来,是一种契约或者协议,是一层提供给另一层的接口(可以想象成OSI各层之间的关系)
在某一层中有多个类协作实现这个层的功能,通过接口暴露出去。但这些类之间会有层次关系(is a,has a)
Q:一个方法加abstract和不加abstract有什么区别?就是说不加有什么关系?加了又会怎样?
A:一方法要是加abstract,那么这个方法就是抽象的,须由子类去实现
抽象方法必须在抽象类当中,也就是说,一个类只要有一个方法是抽象的,那么这个类就必须是抽象类
抽象类里面的方法不一定要抽象的,也可以全都不是抽象的
抽象类不能实例化!
所以可以想到,当你不想让你的类被别人实例化,只想这个类的子类可以实例化,那么只要将这个类声明为abstract的就可以了
(和final的情况蛮相近,当你不想让这个类再有子类化,只要在类的声明前面添加final即可)
不过更多的情况下,我想,还是一个抽象类,他既有部分抽象方法,也有部分具体的方法。
具体的方法是已经定义好的,抽象方法需要由子类去实现。(个人感觉和C++的virtual很相近,不过abstract是纯虚的)
 
那么为什么要有抽象类呢?我说过这关系到你类的设计问题。(当然还有不想被实例化)
譬如经常举的一个例子
abstract class Shape{ 
    public abstract void draw(); 
    public abstract void reDraw(); 

class Triangle extends Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 

class Circle extends Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 

当然你可以这样设计
class Shape{ 
    public void draw(){} 
    public void reDraw(){} 
}
这样设计有2个不妥之处:
1.不符合逻辑。Shape是你针对具体的事物(Triangle,Circle)抽象出来的。它定义的方法应该到子类中去实现
2.在设计的时候就应该认识到,实例化Shape是没有意义的,因为Shape本身只是一种抽象。现在别人如果拿来就可以实例化了,这样的操作方式违背了当初设计的意愿。而且会存在潜在的危险。(当前的实现可能看不出危险)
那么,如果把Shape定义成Interface呢?
当然可以
Interface Shape{ 
    void draw(); 
    void reDraw(); 

class Triangle implements Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 

class Circle implements Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 
}
只不过现在子类Triangle,Circle和Shape之间的关系就不是父子了。
这样设计其实违背了常理,因为在我们的观念中,Triangle和Circle本来就应该是一种Shape
而不应该是他们都遵守一定的操作方式(void draw(),void reDraw())
如何扩展这些设计呢?譬如说为Triangle和Circle添加erase方法?
如果是class Shape这样的设计,很简单,只要
abstract class Shape{ 
    public abstract void draw(); 
    public abstract void reDraw(); 
    public void erase(){ 
        Window window=WindowContainer.getCurrentWindow(); 
        window.clean(); 
    } 
}
Triangle和Circle的代码可以原封不动!
你可能会问,为什么不把erase()设计成为abstract的。你当然可以把erase()设计成abstract的,然后在子类中重写这个方法,提供子类自己的实现。
但是,在现实当中,你可能更赞同是用上面的设计。的确,erase方法只要简单的进行擦除就可以了,不是吗?
这样一来,扩展就变的很容易了。
如果是Interface Shape的设计,那你做的事可就多了
Interface Shape{ 
    void draw(); 
    void reDraw(); 
    void erase(); 

class Triangle implements Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 
    public void erase(){  
        Window window=WindowContainer.getCurrentWindow(); 
        window.clean(); 
    } 

class Circle implements Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 
    public void erase(){ 
        Window window=WindowContainer.getCurrentWindow(); 
        window.clean(); 
    } 
}
所有相关的代码,你都要修改!即便他们都做同样的事情!
这样扩展实在是太麻烦了!
你也许和我想的一样,定义接口本身的目的就是告诉大家,任何实现此接口的类,都有自己的实现方法!
我们定义接口的目的是:你们的实现可以不一样,但是你们暴露的接口一定要一致
可以举java类库当中的一个设计,Thread
如果你要设计一个线程类,该怎么办?
两种方法:
//通过继承Thread类来实现 
class MyThread extends Thread{ 
    public void run(){}//覆盖Thread的run方法 

//通过实现Runnable接口来实现 
class MyThread implements Runnable{ 
    public void run(){}//实现Runnable的run方法,MyThread和YourThread的实现都不一样 

(看过Thread的源代码,你就会发现,其实Thread实现了Runnable)
到此,你应该可以看的出来,为什么要继承Thread和为什么要实现Runnable了
 
另外一个抽象类的使用方法是我最近在C++的项目中学习到的。可能你已经会了
 
package com.pamigo.shp; 
abstract class Shape{ 
    public abstract void draw(); 
    public abstract void reDraw(); 
    public void erase(){ 
        doErase(); 
        Window window=WindowContainer.getCurrentWindow(); 
        window.clean(); 
    } 
    protected abstract void doErase(); 

class Triangle extends Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 
    protected void doErase(){ 
        MusicBox.sing("Amazing Grace"); 
    } 

class Circle extends Shape{ 
    public void draw(){...} 
    public void reDraw(){...} 
    protected void doErase(){ 
        WindowBox.popUp("I'll go!"); 
    } 

package com.pamigo.clnt; 
class User{ 
    public static void main(String[] args){ 
        Shape shp=new Triangle(); 
        shp.draw(); 
        shp.erase(); 
    } 
}
//注意我的权限修饰符
我想表达的意思就是,对外界来说,User只能看到Shape的erase方法。
erase方法必须要做Window的清除工作,但为了给子类提供机会做自己的清除工作,所以设计了
protected abstract void doErase();
因为是protected权限,所以User是看不见的。
不管是Circle还是Triangle,都会有自己的doErase方法。并且他们都会在用户调用shp.erase();时被正确的调用
并且不用关心Window是如何被清除的!
这类似于一种回调函数的方式,你可以这么认为。
==========================================================================
abstract作为修饰符,可以修饰类和方法。

1>.抽象类: 不能手动创建对象(JVM可以创建抽象类的对象),但是可以声明抽象类型的引用.

public class TestAbstract1{

public static void main(String[] args){

//Animal a=new Animal();

//error

Animal a=null;

a=new Dog();

}

}

abstract class Animal{      }

class Dog extends Animal{       }

2>.抽象方法:有方法名的定义,没有实现,(只定义了能做什么,没定义怎么做)    抽象方法的好处是允许方法的定义和实现分开。

abstract class Animal{

public abstract void eat();

}

抽象类和抽象方法的关系:含有抽象方法的类一定是抽象类,抽象类里不一定含有抽象方法

抽象类存在的意义是用来被继承的。一个类继承了一个抽象类,必须实现抽象类里面所有的抽象方法,否则,此类也是抽象类。

abstract class Animal{

public void run(){}

public abstract void sleep();

public abstract void eat();

}

class Dog extends Animal{

public void sleep(){

System.out.println("Dog sleep.");

}

public void eat(){

System.out.println("Dog eat.");

}

}

abstract class Cat extends Animal{

public void eat(){

System.out.println("Cat eat.");

}

}

可以声明父类类型子类对象,利用多态调用抽象方法

public class TestAbstract1{

public static void main(String[] args){

Animal a=null;

a=new Dog();

a.sleep();

a.eat();

}

}

抽象类有构造方法,有父类的,也遵循单继承的规律

class E{}

abstract class Animal extends E{

public Animal(){

super();

}

}

Java中abstract类和abstract方法的相关问题相关推荐

  1. Java中String类的concat方法___java的String字符串的concat()方法连接字符串和“+“连接字符串解释

    Java中String类的concat方法 在了解concat()之前,首先需要明确的是String的两点特殊性. 长度不可变 值不可变 这两点从源码中对String的声明可以体现: private ...

  2. Java 中Date类getTime()的方法

    Java 中Date类getTime()的方法 1.getTime() /**Returns the number of milliseconds since January 1, 1970, 00: ...

  3. Java中Scanner类的close()方法所引发的错误

    Java通过系统类System实现标准输入/输出的功能 我们经常通过实例化Scanner类的方式实现从键盘的数据输入 但其中的如果对其中一些细节不了解,就会引发不能理解的错误 比如close方法: i ...

  4. Java中BigInteger类的使用方法详解,常用最全系列!

    原创博文,欢迎转载,转载时请务必附上博文链接,感谢您的尊重. 在 Java 中,有许多数字处理的类,比如 Integer类,但是Integer类有一定的局限性. 我们都知道 Integer 是 Int ...

  5. JAVA中Math类的random()方法使用

    使用了Math类的random()方法, 由于Math类是出于java.lang包(Package),故使用时不必import这个包. 此外本例还使用了移位运算符 /*** 使用了Math类的rand ...

  6. 关于Java中String类的intern()方法

    首先intern()方法的定义:当调用这个方法的时候,如果字符串常量池中有这个对象,就把常量池中的这个对象返回,没有就把当前对象加入到常量池并且返回当前对象的引用: jdk1.6之前:将对象存入常量池 ...

  7. Java中BigDecimal类的使用方法详解,常用最全系列!

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.对于Double类型的运算,通常使用此类处理,来有效避免精度问题. 下面,我们从五个功能点 ...

  8. JAVA中String类的intern()方法的作用

    2019独角兽企业重金招聘Python工程师标准>>> 一般我们变成很少使用到 intern这个方法,今天我就来解释一下这个方法是干什么的,做什么用的 首先请大家看一个例子: [ja ...

  9. java中Scanner类的使用方法

    1.Scanner类简介 Scanner类主要用于扫描用户从控制台输入的文本,即当用户需要输入数据时,调用java.util包中的Scanner类,Scanner类能获取用户所输入的数据. 2.如何使 ...

  10. java中scanner类的常见方法用法总结

    java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入. 首先要先创建一个Scanner对象. Scanner sc = new Scanner ...

最新文章

  1. 【Ubuntu】安装中文输入法、终端不支持中文的解决方法
  2. 10分钟教你看懂mongodb的npm包
  3. python整理数据_Python数据类型整理
  4. echart 折线图设置y轴单位_如何让echarts中y轴的单位位于数值的右上角
  5. LeetCode_链表类
  6. C#IList 取区间数据
  7. linux脚本传参修改配置文件,shell脚本修改配置文件指定行的值
  8. 更好的默认NullPointerException消息是否会传入Java?
  9. python3基础:字符串、文本文件
  10. 同步容器和并发容器的区别
  11. (转载)面试时,你会问面试官哪些问题?
  12. Python图像处理丨OpenCV+Numpy库读取与修改像素
  13. selenium BY定位
  14. 【uni-app系列】uni-ui扩展组件和uViewUI的安装使用
  15. golang base64解码编码实现
  16. 犹太人很会赚钱?一老板用犹太人的思维做生意,一年赚了200多万!
  17. Vue进阶(六十三):如何使浏览器打开时,默认的文档模式就是标准模式
  18. 计算机英语900句小e,计算机英语100句
  19. sql大全超详细【转】
  20. 大数据基础——知识汇总

热门文章

  1. 如何识别一个指针式的时种的时间?
  2. IIS没有.net版本选择标签问题
  3. [?]Oracle 10g sqlplus 的Bug?
  4. c++学习笔记之析构函数
  5. 时频分析:短时傅里叶变换实现(1)
  6. GPU硬件结构和程序具体参数设置
  7. KDE/QT vs GNOME/GTK
  8. 英伟达jetson TX1的caffe-ssd配置
  9. [云炬创业管理笔记]第二章测试1
  10. 科大星云诗社动态20210310