一、抽象类
定义:在普通类的基础上扩充了一些抽象方法 。
1. 抽象方法:只声明而未实现的方法(没有方法体)
- 所有抽象方法使用abstract定义。同时抽象方法所在的类也要用abstract定义,表示抽象类。
- 举例:定义一个抽象类:
抽象类中没有具体实现,因此抽象类不能直接实例化对象
abstract class Person{
private String name;//姓名属性
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
//{}为方法体,所有抽象方法没有方法体{}
public abstract void getPersonInfo();//抽象方法
}
2.抽象类的使用原则
(1)抽象类必须有子类(abstract与final不能同时使用)。
(2)子类覆写抽象类所有的抽象方法(abstract与private不能同时使用)。
(3)抽象类实例化对象,必须通过子类向上转型来实例化对象(抽象类无法直接实例化对象)。
//抽象类的标准操作,也是常用操作。
abstract class Person{
//姓名属性
private String name;
//普通方法
public String getName(){
return this.name;
}
public void setName(String name){
this.name=name;
}
//抽象方法
public abstract void getPersonInfo();
}
//子类继承抽象类
class Student extends Person{
public void getPersonInfo(){
System.out.println("I am a student");
}
}
public class Test{
public static void main(String[] args){
//实例化子类,向上转型
Person per = new Student();
//被子类所覆写的方法
per.getPersonInfo();
}
}
运行结果:I am a student
abstract class Person{
private String name ; // 属性
public String getName(){ // 普通方法
return this.name;
}
public void setName(String name){
this.name = name ;
}
public abstract void getPersonInfo() ; //抽象方法
public static Person getInstance() { //取得A类对象
//定义抽象类的子类 (内部类)
class Student extends Person {
public void getPersonInfo() {
System.out.println("I am a student");
}
}
return new Student();
}
}
public class Test{
public static void main(String[] args) {
Person per = Person.getInstance();
per.getPersonInfo() ; //被子类所覆写的方法
}
}
运行结果:I am a student
3.抽象类的相关规定
(1)抽象类也提供构造方法,并且子类也遵循对象实例化流程:先调用父类构造方法,再调用子类构造方法
abstract class Person{
private String name;
public String getName(){
return name;
}
//父类构造方法
public Person(){
System.out.println("1.**************");
}
//抽象方法
public abstract void fun();
}
class Student extends Person{
//子类构造方法
public Student(){
System.out.println("2.##############");
}
public void fun(){
System.out.println("子类继承抽象类");
}
}
public class Test{
public static void main(String[] args){
new Student();//先调用父类构造方法,再调用子类构造方法
}
}
运行结果:
1.**************
2.##############
//面试题
abstract class Person{
public Person(){//3.调用父类构造
this.print();//4.调用被子类覆写的方法
}
public abstract void print();//抽象方法
}
class Student extends Person{
private int num = 100;//此句在对象new成功后才会用到,此句告诉构造方法要将num赋值为100
public Student(int num){//2.调用子类实例化对象
// super();//3.隐含这一句,实际要先调用父类构造。此时还未执行“将num赋值为100”的操作,就去调用父类构造了。num默认为int的默认值0。
//num=100;//此句在构造方法中隐式实现。
//总的来说,构造方法会隐藏 给变量的赋值操作。
this.num=num;//7.为类中属性初始化
}
public void print(){//5.此时子类对象的属性还没有被初始化
System.out.println(this.num);//6.输出其对应数据类型的默认值,为0
}
}
public class Test{
public static void main(String[] args){
//先调用父类构造方法,再调用子类构造方法。调用父类构造后,调用打印方法,输出num的值0。调用子类构造,在内存中完成num赋值为30,但并未调用打印方法,因而只有一个值。
new Student(30);//1.实例化子类对象
}
}
//父类中num=0,子类中num=30。但由于子类中没有调用打印方法,所以只有一个父类的num值,为0。
运行结果:0
(2)抽象类中可以不定义抽象方法,但仍然无法直接实例化对象。
(3)abstract与final、private不能一起用。
- final声明的类不允许有子类,而abstract抽象类必须有子类。
- 抽象方法必须要被覆写,因此不能用private封装。
(4)抽象类也分为内部抽象类和外部抽象类。- 内部抽象类(了解)可以使用static定义来描述外部抽象类
如果此时在外部抽象类中使用static就会出现语法错误,但是内部抽象类允许使用static
//内部抽象类使用static修饰
abstract class A{//此结果出现几率很低
public abstract void printA();
static abstract class B{
public abstract void printB();
}
}
class x extends A.B{
public void printB(){}
}
注意:对象实例化的核心步骤
①类加载
②类对象的空间开辟
③类对象中的属性初始化(构造方法)
方法可以重写,属性不能重写。