类初始化和实例初始化
- 1.类初始过程
1.一个类要创建实例时需要先加载并初始化该类
main()方法所在的类需要先加载和初始化
2.一个子类要初始化需要先初始化父类
3.一个类初始化就是执行<clinit>()方法,即类classinit方法
a.<clinit>()方法由静态类变量显示赋值代码和静态代码块组成
b.静态类变量显示赋值代码和静态代码块代码按照代码顺序从上到下执行
c.<clinit>()方法只执行一次
- 2.实例初始化过程
* 实例初始化就是执行<inlt>()方法
* a.<init>()方法可能重载有多个,有几个构造器就有几个<init>()方法
* b.<init>()方法由 非静态实例变量显示赋值代码,非静态代码块,对应构造器代码组成
* c.非静态实例变量显示赋值代码,非静态代码块代码 按照代码顺序从上到下执行,而对应构造器的代码最后执行
* d.每次创建实例对象,调用对应构造器,执行的就是对应的<init>()方法
* e.<init>()方法的首行是super()或super(实参列表),即对应父类的<init>()方法
- 3.方法的重写
* 1.哪些方法不可以被重写
* a.final方法
* b.静态方法
* c.private等子类中不可见方法
* 2.对象的多态性
* a.子类中如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码
* b.非静态方法默认的调用对象是this
* c.this对象在构造器或者说<init>方法中就是正在创建的对象
代码实现:
/*
* 父类初始化<clinit>():
* 1.j=jj();---->5
* 2.父类的静态代码块------>1
*
* 父类的实例化方法:
* 1.super()(最前)
* 2.i=ii();----->9
* 3.父类的非静态代码块----->3
* 4.父类构造器(最后)----->2
*
* 非静态方法前面其实有一个默认对象this
* this在构造器(<init>())它表示的是正在创建的对象,因为在这里是Son对象,
* 所以test()执行的是子类的重写代码(面向对象多态)
*
* 这里i=ii()执行的是子类重写的ii()方法
*/
class Father{
private int i=ii();
private static int j=jj();
static {
System.out.print("(1)");
}
Father(){
System.out.print("(2)");
}
{
System.out.print("(3)");
}
public int ii() {
System.out.print("(4)");
return 0;
}
public static int jj() {
System.out.print("(5)");
return 0;
}
}
/**
* 子类初始化<clinit>():
* 1.先初始化父类---->5,1
* 2.j=jj();----->10
* 3.子类的静态代码块;----->6
*
* 子类的实例化方法:
* 1.super()(最前)9,3,2
* 2.i=ii(); ------>9
* 3.子类的非静态代码块-------->8
* 4.子类构造器(最后)----->7
*
* 因为创建两个Son对象,因此实例化方法<init>执行两次
* 932987
*/
class Son extends Father{
private int i=ii();
private static int j=jj();
static {
System.out.print("(6)");
}
Son(){
System.out.print("(7)");
}
{
System.out.print("(8)");
}
public int ii() {
System.out.print("(9)");
return 0;
}
public static int jj() {
System.out.print("(10)");
return 0;
}
}
public class Test{
//(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2)(9)(8)(7)
public static void main(String[] args) {
Son s=new Son();
System.out.println();
Son ss=new Son();
}
}
* Override和Overload的区别?
方法的重写(Overriding)和重载(Overloading)是Java多态性的不同表现。
重写(Overriding)是父类与子类之间多态性的一种表现,而重载(Overloading)是一个类中多态性的一种表现。
如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding) 。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被屏蔽了。
如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型或有不同的参数次序,则称为方法的重载(Overloading)。不能通过访问权限、返回类型、抛出的异常进行重载。
1. Override 特点
1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
4、方法被定义为final不能被重写。
5、对于继承来说,如果某一方法在父类中是访问权限是private,那么就不能在子类对其进行重写覆盖,如果定义的话,也只是定义了一个新方法,而不会达到重写覆盖的效果。(通常存在于父类和子类之间。)
2.Overload 特点
1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int, float), 但是不能为fun(int, int));
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
4、重载事件通常发生在同一个类中,不同方法之间的现象。
5、存在于同一类中,但是只有虚方法和抽象方法才能被覆写。
Ooverride重写要求?
重写的方法与父类方法签名(方法名称和参数列表,参数类型必须相同,而不能是子类)相同(=)
重写方法的访问限定符范围不能低于父类,因为重写就是为了更好的使用的,所以应用范围应该更广一点(>=)
父类的私有方法不能重写
static修饰的方法不能重写(因为它不是通过对象调用的
如果父类中返回类型是八大基本类型、string或void,则必须相同
如果是其他引用类型,则重写方法中必须返回相同类型a或a的子类(<=)
子类重写方法抛出的异常范围要小于父类方法抛出的异常或或不在同个父类下的异常或没有异常(<=)