抽象类就是不能使用new方法进行实例化的类,即没有具体实例对象的类。抽象类有点类似“模板”的作用,目的是根据其格式来创建和修改新的类。对象不能由抽象类直接创建,只可以通过抽象类派生出新的子类,再由其子类来创建对象。当一个类被声明为抽象类时,要在这个类前面加上修饰符abstract.
在抽象类中的成员方法可以包括一般方法和抽象方法。抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型、方法名称和所需的参数,没有方法体,也就是说抽象方法只需要声明而不需要实现。当一个方法为抽象方法时,意味着这个方法必须被子类的方法所重写,否则其子类的该方法仍然是abstract的,而这个子类也必须是抽象的,即声明为abstract.
抽象类中不一定包含抽象方法,但是包含抽象方法的类一定要被声明为抽象类。抽象类本身不具备实际的功能,只能用于派生其子类。抽象类中可以包含构造方法,但是构造方法不能被声明为抽象。
调用抽象类中的方法(抽象方法和非抽象方法),如果方法是static的,直接 抽象类。方法 就可以了;如果是非static的则必须需要一个继承的非抽象类,然后用这个非抽象类的实例来调用方法。
抽象类可以实现接口,接口中的方法 在抽象类中可以不实现,当有子类继承 抽象类时,并且子类不是抽象类时,子类需要将抽象类中的 抽象方法和接口中的方法都实现
抽象类不能用final来修饰,即一个类不能既是最终类又是抽象类。
总结: abstract不能与private、static、final、native并列修饰同一个方法。
注意:子类继承父类方法后,这个子类对象如果执行方法的话,只要子类重写了就执行子类的,不执行父类的。
package xxx.java;
public class AbstractTest {
public static void main(String[] args) {
//一旦Person类抽象了,就不可实例化(不能造对象了)
// Person p1 = new Person();
// p1.eat();
}
}
abstract class Creature{
public abstract void breath();
}
abstract class Person extends Creature{
String name;
int age;
public Person(){
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
//不是抽象方法:有空的方法体
// public void eat(){
//
// }
//抽象方法
public abstract void eat();
public void walk(){
System.out.println("人走路");
}
}
class Student extends Person{
public Student(String name,int age){//父类Person中有构造器,所以子类可以使用父类中的构造器
super(name,age);
}
public Student(){
}
//Student类不能调用父类中的eat方法(抽象方法),要使用eat方法要么额外在子类中把父类Person中的eat方法重写,要么把Student类也弄成抽象类(abstract class Student extends Person)
//即:若子类重写了父类中的所有的抽象方法后,此子类方可实例化;若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
public void eat(){
System.out.println("学生多吃有营养的食物");
}
@Override
public void breath() {//Student类继承Person类,Person类继承Creature类,Creature类用抽象类修饰了,故Student类要调用Creature类中的breath功能,则要么重写breath方法,要么Student类也抽象化
System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
}
}
在Person类中,抽象方法eat要省略方法体:
public abstract void eat();
我们不能直接通过造Person类的对象调用该eat方法(抽象类不能实例化,无法造抽象类的对象去调用该类中的方法),要调用eat方法,只能造Person类的子类(如Student类),在Student类(不再是抽象类)中重写父类中的所有抽象方法(重写之后的eat方法也不再是抽象方法)
注:若子类重写了父类中的所有的抽象方法后,此子类方可实例化;若子类没有重写父类中的所有的抽象方法则此子类也是一个抽象类,需要使用abstract修饰。即:
class Student extends Person{
public Student(String name,int age){//父类Person中有构造器,所以子类可以使用父类中的构造器
super(name,age);
}
public Student(){
}
public void eat(){
System.out.println("学生多吃有营养的食物");
}
@Override
public void breath() {//Student类继承Person类,Person类继承Creature类,Creature类用抽象类修饰了,故Student类要调用Creature类中的breath功能,则要么重写breath方法,要么Student类也抽象化
System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
}
}
改为:
abstract class Student extends Person{
public Student(String name,int age){//父类Person中有构造器,所以子类可以使用父类中的构造器
super(name,age);
}
public Student(){
}
public void eat(){
System.out.println("学生多吃有营养的食物");
}
@Override
public void breath() {//Student类继承Person类,Person类继承Creature类,Creature类用抽象类修饰了,故Student类要调用Creature类中的breath功能,则要么重写breath方法,要么Student类也抽象化
System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
}
}
但如果Student类又变成抽象类,则Student类又不能能通过造Student类的对象去调用Student类中的方法了。即如果不在Student类中重写父类Person中的全部方法,单纯在Student类前加abstract只能保证程序不出错而已。(本人不成熟的见解,有误望指出)
所以,一般来说,要想调用抽象类中的抽象方法,应该造该抽象类(父类)的子类,然后在子类中重写父类的全部方法,然后就可以通过造子类的对象去调用子类中重写过的方法。
JDK7及以前,接口中的方法一定是抽象方法(那么方法前缀没有abstract,也默认有)。
**接口中不能定义构造器的!**意味着接口不可以实例化(不能通过直接new对象去调用接口中的方法)。要用接口,得通过类去实现(implements)的方式来使用。(即把接口转换成类去使用):
package xxx.java1;
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
// Flyable.MIN_SPEED = 2;//就算48行省略了public static final,Flyable.MIN_SPEED依然不能赋值
Plane plane = new Plane();//75行开始重写了fly和stop方法,故可以new对象去调用Plane类中的属性方法了。
plane.fly();//通过传入该接口的实现类Plane的对象plane来调用接口Flyable中的方法
}
}
interface Flyable{
//全局常量
public static final int MAX_SPEED = 7900;//第一宇宙速度
int MIN_SPEED = 1;//可以省略了public static final
//抽象方法
public abstract void fly();
//方法中可以省略了public abstract
void stop();
//Interfaces cannot have constructors接口中不能定义构造器的!意味着接口不可以实例化
// public Flyable(){
//
// }
}
class Plane implements Flyable{
//使用接口中的这两个方法时,由于接口中的方法是抽象方法,故在Plane类中要么重新实现一下这两个方法,要么将Plane类抽象化(class前面加abstract)
//下面重新实现一下这两个方法:
//如果实现类覆盖了接口中的所有抽象方(fly,stop)法,则此实现类就可以实例化
//如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
@Override
public void fly() {
System.out.println("通过引擎起飞");
}
@Override
public void stop() {
System.out.println("驾驶员减速停止");
}
}
其中,Flyable接口中的方法是抽象方法,和上面讲的调用抽象方法的手法一样,我们需要在实现类Plane中重写Flyable接口中的所有方法,然后再造实现类Plane的对象plane去调用Flyable接口中的相应的方法(如fly)。
如果只是在class Plane implements Flyableqian前面加上abstract,虽然可避免报错,但还是无法调用Flyable接口中的方法(抽象类无法实例化)。