类初始化过程
- 一个类要创建实例需要先加载并初始化该类
a.main方法所在的类需要先加载和初始化
2.一个子类要初始化要先初始化父类
3.一个类初始化就是执行<clinit>()方法
a.<clinit>()方法由静态类变量显示赋值代码和静态代码块组成
b.静态类变量显示赋值代码和静态代码块代码是从上到下按顺序执行的
c.<clinit>()方法只执行一次
实例初始化过程
- 实例初始化就是执行<init>()方法
a.<init>()方法可能重载有多个,有几个构造器就有几个<init>()方法
b.<init>()方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成
c.非静态实例变量显示赋值代码和非静态代码块代码从上到下按顺序执行,而对应构造器的代码最后执行
d.每次创建实例对象,调用对应构造器,执行的就是对应的<init>方法
e.<init>方法的首行是super()或super(实参列表),即父类的<init>方法
通过上面知识点一起看下面这个“父子”面试题
Father.java
package com.java_foundation.test_1;
/**
* @program: java_foundation
* @description: 父类
* 类初始化 clinit
* 1)静态类变量赋值 j = method()
* 2)父类的静态代码块
* 类的实例化方法 init
* 1)super()(最前)
* 2)非静态变量赋值 i = test()
* 3)子类的非静态代码块
* 4)子类的无参构造(最后)
*
* 非静态方法前面其实有一个默认的对象this
* this在构造器表示正在创建对象,因为这里是在创建子类对象。所以test()执行的
* 是子类重写的代码(多态)
*
* i=test()执行子类的test()
* @author: xiongbangwen <Email>xiongbangwen@163.com</Email>
* @create: 2020-05-30 22:32
**/
public class Father {
private int i = test();
private static int j = method();
static {
System.out.print("1)");
}
Father(){
System.out.print("2)");
}
{
System.out.print("3)");
}
public int test() {
System.out.print("4)");
return 1;
}
public static int method() {
System.out.print("5)");
return 1;
}
}
Son.java
package com.java_foundation.test_1;
/**
* @program: java_foundation
* @description: 子类
* 先初始化父类 Father
* 再初始化子类 Son
* 类初始化 clinit
* 1)静态类变量赋值 j = method()
* 2)父类的静态代码块
* 类的实例化方法 init 对象创建几次就走几次
* 1)super()(最前)
* 2)非静态变量赋值 i = test()
* 3)子类的非静态代码块
* 4)子类的无参构造(最后)
*
* @author: xiongbangwen <Email>xiongbangwen@163.com</Email>
* @create: 2020-05-30 22:32
**/
public class Son extends Father{
private int i = test();
private static int j = method();
static {
System.out.print("6)");
}
Son(){
// super(); //写不写都在,在子类构造器一定会调用父类的构造器
System.out.print("7)");
}
{
System.out.print("8)");
}
public int test() {
System.out.print("9)");
return 1;
}
public static int method() {
System.out.print("10)");
return 1;
}
}
Test.java
package com.java_foundation.test_1;
/**
* @program: java_foundation
* @description: 测试类
* @author: xiongbangwen <Email>xiongbangwen@163.com</Email>
* @create: 2020-05-30 22:33
**/
public class Test {
public static void main(String[] args) {
Son s1 = new Son();
System.out.println();
Son s2 = new Son();
//输出
//5)1)10)6)9)3)2)9)8)7)
//9)3)2)9)8)7)
}
}
方法的重写Override
- 哪些方法不可以被重写
final方法 、 静态方法 、private 等子类不可见的
2.对象的多态性
a.子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码
b.非静态方法默认的调用对象是this
c.This对象在构造器或init方法中就是正在创建的对象
Override和 overload的区别?
Override是让类以统一的方式处理不同类型数据的一种手段,实质表现就是多个具有不同的参数个数或者类型的同名函数(返回值类型可随意,不能以返回类型作为重载函数的区分标准)同时存在于同一个类中,是一个类中多态性的一种表现(调用方法时通过传递不同参数个数和参数类型来决定具体使用哪个方法的多态性)。
overload是父类与子类之间的多态性,实质是对父类的函数进行重新定义,如果在子类中定义某方法与其父类有相同的名称和参数则该方法被重写,不过子类函数的访问修饰权限不能小于父类的;若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法,如需父类中原有的方法则可使用 super 关键字。