抽象类只是描述一种抽象的概念,描述其子类所共有的属性和方法,即只定义了方法的声明但不包含具体的实现。抽象类不能被实例化为一个对象,即不能用new 关键字为抽象类对象分配空间,继承抽象类的子类可以对其进行具体的实现。因为抽象类也存在各种属性,因此抽象类中也可以有构造方法
抽象类和抽象方法定义的方式都是在class 或方法名之前加上abstract关键字。
抽象方法在定义上与普通方法一致,需要返回值类型、方法名和参数列表,不同的是抽象方法没有方法体。抽象方法不能用private修饰
抽象类中既可有抽象方法也可以有实例方法。
抽象类不能用final修饰,因为final不能被继承
//抽象类,既可以有抽象方法,有可以有实例方法
abstract class Person{
public static final String country="中国";
private String name;
public Person(){
System.out.println("抽象类Person的无参构造方法 ");
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
//抽象方法,只有声明没有方法体
public abstract void tell();
}
class Student extends Person{
public Student(){
System.out.println("Student类的无参数构造方法");
}
public void tell(){
System.out.println("我叫"+getName()+",是一名"+country+"人!");
}
}
public class AbstractTest{
public static void main(String[] args){
Student stu=new Student();
stu.setName("小米");
stu.tell();
}
}
抽象类可以定义构造方法,因此子类就可以通过super关键字调用抽象类的抽象方法。
若父类没有无参数构造,那么子类使用父类构造时必须用super指明使用父类的哪个构造
若子类不能实现父类的方法,则要将该子类继续定义为抽象类
abstract class Shape{
private float width;
private float high;
public Shape(){
}
public Shape(float width,float high){
this.width=width;
this.high=high;
}
public float getWidth(){
return width;
}
public float getHigh(){
return high;
}
public abstract void area();
public abstract void Circumference();
}
class Rectangle extends Shape{
public Rectangle(){
}
public Rectangle(float width,float high){
super(width,high);
}
public void area(){
System.out.println("矩形面积:"+(getWidth()*getHigh()));
}
public void Circumference(){
System.out.println("矩形周长:"+(getWidth()+getHigh())*2);
}
}
abstract class Oval extends Shape{
//若子类不能实现父类的方法,则要将该子类继续定义为抽象类
public abstract void area();
public abstract void Circumference();
}
public class AbstractTest{
public static void main(String[] args){
Rectangle re=new Rectangle(1.5F,2.0F);
re.area();
re.Circumference();
}
}
多态:抽象类的实例化对象可以通过其子类实例化。
抽象类的三种实现方式:
1.在外部定义普通类继承抽象类
2.在抽象类中的静态方法通过匿名内部类实现
2.在抽象类中的静态方法内部用方法内部类实现
public class Poly_AbstractTest{
public static void main(String[] args){
Person person=new Student("刘明");
System.out.println(person.getPersonInfo());
Person person2=new Teacher("张三");
System.out.println(person2.getPersonInfo());
Person person3=Person.getPersonObject();
System.out.println(person3.getPersonInfo());
}
}
abstract class Person{
public Person(String name ){
this.name=name;
}
private String name ;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
abstract String getPersonInfo();
//静态方法可通过类名直接访问方法内部类不允许使用任何访问修饰符
public static Person getPersonObject(){
//1.方法内部类
/*
class Worker extends Person{
public Worker(String name){
super(name);
}
public String getPersonInfo(){
return "工人姓名"+this.getName();
}
}*/
//2.匿名内部类-->必须继承一个父类或实现一个接口
return new Person("王五"){
public String getPersonInfo(){
return "工人姓名:"+this.getName();
}
};
}
}
class Student extends Person{
public Student(String name){
super(name);
}
public String getPersonInfo(){
return "学生姓名:"+this.getName();
}
}
class Teacher extends Person{
public Teacher(String name){
super(name);
}
public String getPersonInfo(){
return "老师姓名:"+this.getName();
}
}
当抽象列与继承、this、super配合使用用时,其执行顺序是:
先调用当前new的对象的构造函数,进入构造函数后第一行隐含为super();即调用父类的构造。接着执行完父类的构造函数,再返回子类的构造函数依次执行。
abstract class A{
public A(){//4.父类构造方法
this.print();//5.调用B的print方法,因其为抽象方法,向子类中寻找方法的实现
System.out.println("测试A父类的构造函数第几步执行");
}
public abstract void print();
}
class B extends A{
private int num=100;
public B(int num){//2.调用B的构造方法
super();//3.调用父类的构造方法,无参数传递,默认为0
this.num=num;//7.为子类中属性赋值100
System.out.println("测试B子类的构造函数第几步执行");
}
public void print(){//6.调用子类的print方法
System.out.println(this.num);//7.输出30
}
}
public class AbstractTest{
public static void main(String[] args){
new B(30).print();//1.实例化子类对象
}
}