一、类的成员
1、属性:成员变量
2、方法:成员方法
3、构造器:构造方法
4、代码块:初始化块
5、内部类
二、非静态代码块
1、非静态代码块格式
【修饰符】 class 类名{
{
非静态代码块;
}
}
2、非静态代码中的代码执行时机
(1)在“每次”创建对象的时候执行;
(2)比构造器要早;
三、实例初始化
1、实例初始化是什么?
实例初始化过程:每次创建对象时,为对象进行初始化的操作。
2、对象的初始化有那几部分组成?
(1)成员变量显示赋值;
(2)执行非静态代码块;
(3)执行构造器;
3、实例初始化是怎样的?
Java 编译器其实,会把上面三个部分的代码,合成一个叫做 <init>(【形参列表】)实例初始化方法。
即 编译后的 .class 字节码信息中,是没有构造器这个概念的。
<init>(【形参列表】) 实例初始化方法的代码就是由三个部分组成的:
(1)成员变量显示赋值的代码;
(2)非静态代码块中的代码;
(3)构造器中的代码;
注意:
① 其中(1)和(2)将会按照先后顺序执行,而构造器一定是它们当中的最后执行。
② 而且,有几个构造器,就会有几个实例初始化方法。那么当我们创建对象的时候,调用对应的构造器时,其实执行的是对应的实例初始化方法<init>(【...】)
4、
四、案例
1、案例一
1 public class TestInit {
2 public static void main(String[] args) {
3 MyClass my1 = new MyClass();//调用无参构造
4 MyClass my2 = new MyClass("test");//调用有参构造
5
6 System.out.println("-----------------");
7
8 Demo d1 = new Demo();//调用无参构造,本质上是调用<init>()实例初始化方法
9 Demo d2 = new Demo("test");//调用有参构造,本质上是调用<init>(形参列表)实例初始化方法
10 }
11 }
12 class MyClass{
13 private String str = "hello";//显式赋值
14
15 public MyClass(){
16 System.out.println("无参构造");
17 }
18 public MyClass(String str){
19 this.str = str;
20 System.out.println("有参构造");
21 }
22
23 {
24 System.out.println("非静态代码块");
25 }
26 }
27
28 class Demo{
29 {
30 System.out.println("非静态代码块1");
31 }
32
33 private String str = assign();//调用方法,来为str进行显式赋值
34
35 public Demo(){
36 System.out.println("无参构造");
37 }
38 public Demo(String str){
39 this.str = str;
40 System.out.println("有参构造");
41 }
42
43 {
44 System.out.println("非静态代码块2");
45 }
46
47 public String assign(){
48 System.out.println("assign方法");
49 return "hello";
50 }
51 }
52
53 //运行结果
54 非静态代码块
55 无参构造
56 非静态代码块
57 有参构造
58 -----------------
59 非静态代码块1
60 assign方法
61 非静态代码块2
62 无参构造
63 非静态代码块1
64 assign方法
65 非静态代码块2
66 有参构造
2、案例二
1 public class TestInit {
2 public static void main(String[] args) {
3 /*
4 Father f = new Father();
5 //父类的无参构造
6 */
7
8 /*
9 * Son s = new Son();
10 * 父类的无参构造
11 子类的无参构造
12 */
13
14 //Son s2 = new Son("test");
15 /*
16 * 父类的无参构造
17 子类的有参构造
18 */
19
20 Son s3 = new Son("test", 10);
21 /*
22 * 父类的无参构造
23 子类的有参构造1
24 子类的有参构造2
25 */
26 }
27 }
28 class Father{
29 public Father(){
30 System.out.println("父类的无参构造");
31 }
32 }
33 class Son extends Father{
34 private String str;
35 private int num;
36
37 public Son(){
38 //隐含了super(); 子类的构造器中一定会调用父类的构造器,默认调用父类的无参构造
39 System.out.println("子类的无参构造");
40 }
41
42 public Son(String str){
43 //隐含了super()
44 this.str = str;
45 System.out.println("子类的有参构造1");
46 }
47
48 public Son(String str,int num){
49 this(str);
50 this.num = num;
51 System.out.println("子类的有参构造2");
52 }
53 }
54
55 //运行结果
56 父类的无参构造
57 子类的有参构造1
58 子类的有参构造2
3、案例三
1 /* 父子类的实例初始化过程:
2 * (1)先执行父类的实例初始化方法
3 * 它由三部分:
4 * ①成员变量的显式赋值
5 * ②非静态代码块
6 * ③构造器
7 * (2)再执行子类的实例初始化方法
8 * 它由三部分:
9 * ①成员变量的显式赋值
10 * ②非静态代码块
11 * ③构造器
12 *
13 * super()或super(实参列表)之前说的是调用父类的构造器,其实是调用父类对应的实例初始化方法
14 * super()或super(实例列表)之前说的是在子类构造器的首行,其实是在子类实例初始化方法的首行
15 */
16 public class TestInit2 {
17 public static void main(String[] args) {
18 Zi z = new Zi();//312645
19 }
20 }
21 class Fu{
22 private String strFu = assignFu();
23 {
24 System.out.println("(1)父类的非静态代码块");
25 }
26 public Fu(){
27 System.out.println("(2)父类的无参构造");
28 }
29 public String assignFu(){
30 System.out.println("(3)父类的assignFu()");
31 return "fu";
32 }
33 }
34 class Zi extends Fu{
35 private String strZi = assignZi();
36 {
37 System.out.println("(4)子类的非静态代码块");
38 }
39 public Zi(){
40 //super() ==>调用父类的实例初始化方法,而且它在子类实例初始化方法的首行
41 System.out.println("(5)子类的无参构造");
42 }
43
44 public String assignZi(){
45 System.out.println("(6)子类的assignZi()");
46 return "zi";
47 }
48 }
49
50 //运行结果
51 (3)父类的assignFu()
52 (1)父类的非静态代码块
53 (2)父类的无参构造
54 (6)子类的assignZi()
55 (4)子类的非静态代码块
56 (5)子类的无参构造
4、案例四
1 public class TestInit3 {
2 public static void main(String[] args) {
3 Er r = new Er();//612645,因为子类重写了assign()
4
5 // Ba b = new Ba();
6 }
7 }
8 class Ba{
9 private String str = assign();
10 {
11 System.out.println("(1)父类的非静态代码块");
12 }
13 public Ba(){
14 System.out.println("(2)父类的无参构造");
15 }
16 public String assign(){
17 System.out.println("(3)父类的assign()");
18 return "ba";
19 }
20 }
21 class Er extends Ba{
22 private String str = assign();
23 {
24 System.out.println("(4)子类的非静态代码块");
25 }
26 public Er(){
27 //super() ==>调用父类的实例初始化方法,而且它在子类实例初始化方法的首行
28 System.out.println("(5)子类的无参构造");
29 }
30
31 public String assign(){
32 System.out.println("(6)子类的assign()");
33 return "er";
34 }
35 }
36
37
38 //运行结果
39 (6)子类的assign()
40 (1)父类的非静态代码块
41 (2)父类的无参构造
42 (6)子类的assign()
43 (4)子类的非静态代码块
44 (5)子类的无参构造
六、总结
实例初始化过程:
实例初始化方法就是执行类的 <init>() 方法:
- <init>() 方法可能重载有多个,有几个构造器就有几个 <init>方法;
- <init>() 方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成;
- 非静态实例变量显示赋值代码和非静态代码块从上到下顺序执行,而对应构造器的代码最后执行;
- 每次创建实例对象,调用对应构造器,执行的就是对应的<init>方法;
- <init> 方法的首行是 super() 或 super(实参列表),即对应父类的 <init>() 方法;