------- android培训、java培训、期待与您交流! ----------
当多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那么多个类不需要再定义这些属性和行为,只需要
继承单独的那个类即可。多个类称为子类,单独这个类称为父类或超类。子类可以直接访问父类中的非私有的属性和行为。
通过extends关键字让类与类之间产生继承关系。
继承的出现提高代码的复用性,并提供了多态的前提。
java中只支持单继承,不支持多继承,因为多继承容易带来安全隐患:
当功能内容不同时,子类对象不确定要运行哪一个。但java保存了这种机制,通过多实现来完成。
但支持多层继承体系。
想要使用体系,先查阅体系父类的描述,因为父类中的定义的是该体系的共性内容。
定义继承时,不能为了获取某个类中的属性或行为而定义继承,必须要确定两个类间有"is a "的关系,否则没有继承关系。
为什么在具体调用时,要创建子类对象呢?
1.因为有可能父类不能创建的对象
2.创建子类对象可以有共性和特有属性即方法。
当子类创建对象时,会先加载父类的字节码文件,然后再加载子类的字节码文件。
在堆内存中会同时存在父类和子类的相同属性,在方法区中同时存在父类和子类的方法。
super和this的使用方法基本相同,this代表本类对象的引用,super代表父类对象的引用。
当父类中定义非私有属性时,在建立子类对象时,子类中没有定义该属性,那么调用该属性时,可以同时用this或者super来调用
该属性,如this.name或者super.name, 可以理解为子类继承父类的该属性,或者this和super都指向了子类对象。
函数的另一个特性:覆盖
子类继承父类时,沿袭了父类的功能,子类虽然具备该功能,但功能的具体内容有所改变,可以定义和父类相同的功能方法,来
保留父类功能定义,并重写功能内容。实现子类的特有功能。称之为函数的覆盖。
注意: 子类覆盖父类,必须保证子类的访问权限大于或等于父类,且父类的权限不能为私有。静态只能覆盖静态。
子类的实例化过程
在对子类对象初始化时,父类的构造函数也会运行。因为子类的构造函数第一行有一条隐式的语句super();
即会访问父类中的空参数的构造函数。 而且子类中所有的构造函数默认第一行都是super();
class Fu
{
int num = 4;
Fu()
{
System.out.println("fu run"+num);
}
Fu(int num)
{
this.num = num;
System.out.println("fu run..."+num);
}
}
class Zi extends Fu
{
//int num ;当子类中没有定义num变量时,子类初始化时会沿袭父类num的值
int num;
/*当子类中也定义了num变量时,子类构造函数初始化时,通过super()调用父类构造函数而父类构造函数中调用了num
时,父类构造函数中的num调用的是父类中的num值,子类构造函数中调用的num是子类中的num值。因为在构造函数初始化
前,对象已经进行特有属性的显示初始化了。
*/
Zi()
{
System.out.println("zi run"+num);
}
Zi(int num)
{
//super();默认调用父类空参数构造函数
//this();如果有this()时,会先调用本类中的空参数构造函数,在调用本类空参数构造函数时,又会先调用父类的空参数构造函数。
//super(num);如果自定义super语句指定父类的具体构造函数,就会调用对应父类的构造函数。
this.num = num;
System.out.println("zi fun..."+num);
}
}
class ExtendsDemo
{
public static void main(String[] args)
{
Zi z1 = new Zi();
Zi z2 = new Zi(5);
}
}
为什么子类一定要访问父类中的构造函数:
因为父类中的数据子类可以直接获取,子类在对象初始化前需要参考父类是如何对这些数据进行初始化的,所以要先访问父类的
构造函数。可以在子类构造函数中自定义super语句来指定访问父类的具体构造函数。
注意: super语句一定要定义在子类构造函数的第一行。
结论:
子类的所有构造函数,默认都会访问父类中的空参数的构造函数。
因为子类每一个构造函数内的第一行默认都会有一句隐式的super();
当父类中没有空参数的构造函数时,子类必须手动通过super语句来指定访问父类中的构造函数。
当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少有一个构造函数会访问父类中的构造函数。
final:最终,作为一个修饰符。
1.final可以修饰类,也可以修饰方法,变量。
2.final修饰的类不能被继承。为了避免被子类复写。
3.final修饰的方法不能被复写。
4.final修饰的变量时一个常量只能复制一次,既可以修饰成员变量,也可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,这时为了增强阅读性,给这些值起个名字,方便与阅读。
而这个值不需要改变,所以加上final修饰。作为常量,全部大写,单纯间用_连接。
5.内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
6. final只对引用的”值“(即内存地址 )有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会
导致编译期错误。至于它所指向的对象的变化,final是不负责的。
final StringBuffer sb1 = new StringBuffer("aaa");
final StringBuffer sb2 = new StringBuffer("bbb");
sb1=sb2;//编译不通过,无法为最终变量分配地址值