子类的实例化过程
子类中所有的构造函数默认都会访问父类中空参数的构造函数。
因为每一个构造函数的第一行都有一条默认的语句super();。
子类会具备父类中的数据,所以要先明确父类是如何对这些数据初始化的。
为什么子类实例化的时候要访问父类中的构造函数呢?
那是因为子类继承了父类,获取到了父类中内容(属性),所以在使用父类内容之前,要先看父类是如何对自己的内容进行初始化的。
class Fu
{
Fu(){
super();
//调用的是子类的show方法,此时其成员变量 num还未进行显示初始化
show();
return;
}
void show()
{
System. out.println("fu show" );
}
}
class Zi extends Fu
{
int num = 8;
Zi()
{
super();
//通过super初始化父类内容时,子类的成员变量并未显示初始化,等super()父类初始化完毕后,才进行子类的成员变量显示初始化
return;
}
void show()
{
System. out.println("zi show..." + num);
}
}
class ExtendDemo
{
public static void main(String[] args)
{
Zi z = new Zi();
z.show();
}
}
总结:
一个对象实例化过程,以Person p = new Person();为例:
1、JVM会读取指定的路径下的Person.class文件,并加载进内存,并会先加载Person的父类(如果有直接的父类的情况下)。
2、在内存中开辟空间,并分配地址。
3、并在对象空间中,对对象的属性进行默认初始化。
4、调用对应的构造函数进行初始化。
5、在构造函数中,第一行会先到调用父类中构造函数进行初始化。
6、父类初始化完毕后,再对子类的属性进行显示初始化。
7、再进行子类构造函数的特定初始化。
8、初始化完毕后,将地址值赋值给引用变量。
final关键字
class Fu
{
void method()
{
}
}
class Zi extends Fu
{
public static final double PI = 3.14;
void method()
{
System. out.println(PI);
}
}
class FinalDemo
{
public static void main(String[] args)
{
Zi zi = new Zi();
zi.method();
}
}
final可以修饰类,方法,变量。
final修饰的类不可以被继承。
final修饰的方法不可以被覆盖。
final修饰的变量是一个常量,只能被赋值一次
抽象类
抽象类中是否有构造函数?
答:有,用于给子类对象进行初始化。
抽象关键字abstract不可以和哪些关键字共存?
答:private、static、final。
抽象类中可不可以没有抽象方法?
答:可以,但是很少见。目的就是不让该类创建对象,AWT的适配器对象就是这种类。通常这个类中的方法有方法体,但是却没有内容。
抽象类和一般类的区别?
答:
相同点:
抽象类和一般类都是用来描述事物的,都在内部定义了成员。
不同点:
①一般类有足够的信息描述事物。
抽象类描述事物的信息有可能不足。
②一般类中不能定义抽象方法,只能定义非抽象方法。
抽象类中可定义抽象方法,同时也可以定义非抽象方法。
③一般类可以被实例化。
抽象类不可以被实例化。
抽象类一定是个父类吗?
答:是的,因为需要子类覆盖其方法后才可以对子类实例化
接口
当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口。
格式:interface {}
接口中的成员修饰符是固定的:
成员常量:public static final
成员函数:public abstract
由此得出结论,接口中的成员都是公共的权限。
接口是对外暴露的规则。
接口是程序的功能扩展。
interface Demo
{
public static final int NUM = 4;
public abstract void show1();
public abstract void show2();
}
class DemoImpl implements /*实现*/Demo
{
public void show1(){}
public void show2(){}
}
class InterfaceDemo
{
public static void main(String[] args)
{
DemoImpl d = new DemoImpl();
System. out.println(d.NUM);
System. out.println(DemoImpl.NUM);
System. out.println(Demo.NUM);
}
}
注意:
- ①虽然抽象类中的全局变量和抽象方法的修饰符都可以不用写,但是这样阅读性很差。所以,最好写上。
- ②类与类之间是继承关系,类与接口直接是实现关系。
- ③接口不可以实例化,只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。否则,这个子类就是一个抽象类。