抽象类的使用限制
抽象类的组成和普通类的区别不大,但是由于有一点点使用以及定义的区别,所以会有以下概念会被忽略
1.抽象类里面由于会存在一些属性,在抽象类中一定会存在抽象方法,目的为属性初始化,并且子类对象初始化时依然满足于,先执行父类构造,再执行子类构造的情况
2.抽象类不能使用final定义:因为抽象类必须有子类,而final定义的类不能有子类
3.外部的抽象类不允许使用static
声明,而内部的抽象类允许使用static声明,使用static声明的内部抽象类就相当于一个外部抽象类,继承的时候使用"外部类.内部类"的形式表示类名称
确定抽象类中存在构造方法
4.任何情况下,如果要执行类中的`static`方法的时候,都可以在没有对象的时候直接调用,对于抽象类也是一样
5.有些时候,由于抽象类只需要一个特定的系统子类操作,所以可以忽略掉外部子类
abstract class A{ // 定义一个抽象类
public A(){
System.out.println("************");
}
public void print(){ // 普通方法
System.out.println("存在普通方法");
}
// 此方法并没有方法体的声明,并且存在有abstract关键字,表示抽象方法
public abstract void func();
}
// 一个子类只能够继承一个抽象类,属于单继承局限
class B extends A{ // B类是抽象类的子类并且是一个普通类
public B(){
System.out.println("#####################");
}
public void func(){
System.out.println("Hello world");
}
}
public class testDemo{
public static void main(String args[]){
A a = new B(); // 向上转型
a.func();
}
}
执行结果
root@079a25844567:/opt/lixinghua/OOP# javac testDemo.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
root@079a25844567:/opt/lixinghua/OOP# java testDemo
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
************
#####################
Hello world
使用内部类的static
声明
abstract class A{ // 定义一个抽象类
// static定义的内部类属于外部类
static abstract class B{
public abstract void print();
}
}
class X extends A.B {
public void print(){
System.out.println("****************");
}
}
public class testDemo{
public static void main(String args[]){
A.B ab = new X();// 向上转型
ab.print();
}
}
输出结果
root@079a25844567:/opt/lixinghua/OOP# javac testDemo.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
root@079a25844567:/opt/lixinghua/OOP# java testDemo
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
****************
抽象类直接调用static
方法
abstract class A{
public static void print(){
System.out.println("*************");
}
}
public class testDemo{
public static void main(String args[]){
A.print();
}
}
输出结果
root@079a25844567:/opt/lixinghua/OOP# javac testDemo.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
root@079a25844567:/opt/lixinghua/OOP# java testDemo
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
*************
对外部隐藏内部子类实现
abstract class A{
public abstract void print();
private static class B extends A { // 内部抽象类的子类
public void print(){ // 覆写抽象类的方法
System.out.println("***********");
}
}
// 这个方法不受实例化对象的控制
public static A getInstance(){
return new B();
}
}
public class testDemo{
public static void main(String args[]){
// 此时取得抽象类对象的时候完全不知道B类的存在
A a = A.getInstance();
a.print();
A.getInstance().print();;
}
}
执行结果
root@079a25844567:/opt/lixinghua/OOP# javac testDemo.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
root@079a25844567:/opt/lixinghua/OOP# java testDemo
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
***********
***********
这样的设计在系统类库之中会比较常见,目的:为用户隐藏不需要知道的子类
分析代码
分析代码执行结果
abstract class A{
public A(){ // 2.调用父类构造方法
this.print(); // 3.调用print()方法
}
public abstract void print();
}
class B extends A{
private int num = 100;
public B(int num){
this.num = num;
}
public void print(){ //4.调用覆写方法
// 此时未对num属性初始化,其值为默认值
System.out.println("num= " + num);
}
}
public class testDemo{
public static void main(String args[]){
new B(30); // 1.执行构造
}
}
执行结果
root@079a25844567:/opt/lixinghua/OOP# vim testDemo.java
root@079a25844567:/opt/lixinghua/OOP# javac testDemo.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
root@079a25844567:/opt/lixinghua/OOP# java testDemo
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
num= 0
解决思路:在任何一个类的构造执行完之前,所有属性的内容都是其对应数据类型的默认值,而子类对构造方法执行之前,一定先执行父类构造,那么此时子类构造由于没有执行,所以num就是0