该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架。

一、构造方法

构造方法(或构造函数)是类的一种特殊方法,用来初始化类的一个新的对象。Java 中的每个类都有一个默认的构造方法,它必须具有和类名相同的名称,而且没有返回类型。构造方法的默认返回类型就是对象类型本身,并且构造方法不能被 static、final、synchronized、abstract 和 native 修饰。

提示:构造方法用于初始化一个新对象,所以用 static 修饰没有意义;构造方法不能被子类继承,所以用 final 和 abstract 修饰没有意义;多个线程不会同时创建内存地址相同的同一个对象,所以用 synchronized 修饰没有必要。

构造方法的语法格式如下:

public class Person {

	/**
* 1.构造方法没有返回值 默认返回类型就是对象类型本身
* 2.构造方法的方法名和类名相同
*/ //无参构造方法
public Person() {
System.out.println("我是无参构造方法");
} //有参构造方法
public Person(String username,Integer age) {
System.out.println("我是有参构造"+"姓名:"+username+" 密码:"+age);
} public static void main(String[] args) {
Person p1=new Person();//调用无参构造 Person p2=new Person("小王",12);//调用有参构造
} }

  

关于构造方法,需要注意:

  • 如何调用:

    • 构造方法在实例化的时候调用,如上述代码中的Person p1=new Person(),这里便调用了Person类的无参构造,构造方法由系统自动调用
  • 构造函数重载
    • 我们知道方法可以重载(方法名相同,参数列表不同),那么构造方法也是方法的一种,当然也可以继承,如上述代码中的两个构造方法,一个无参构造方法,一个带两个参数的构造方法。
    • 当有多个构造方法时,程序会在你创建类时根据你传入的参数决定调用哪个构造方法
  • 默认构造方法
    • 细心的读者可能会有疑问,之前创建类的时候我并没有声明构造函数,但是也可以创建类,是不是可以说类不需要构造函数也可以创建。不是滴,当你没有显示声明构造函数时,程序会自动生成一个默认的无参构造函数
    • 并且该构造函数的权限是随着类的改变而改变的(类为public,构造函数也为public;类改为private,构造函数也改为private);而当该类一旦声明了构造函数以后,java 是不会再给该类分配默认的构造函数。就是说,一旦你声明了构造函数,并且该构造函数有形参,那么你就不能pen ipen=new pen();像这样声明一个对象了。
  • 构造方法作用:
    • 构造函数是用于对象初始化
    • 一个对象建立,构造函数只运行一次,而一般方法可以被该对象调用多次。

二、代码块

1、普通代码块:

普通代码块是我们用得最多的也是最普遍的,它就是在方法名后面用{}括起来的代码段。普通代码块是不能够单独存在的,它必须要紧跟在方法名后面。同时也必须要使用方法名调用它。

public class Test {
public void test(){
System.out.println("普通代码块");
}
}

  

2、构造代码块:

在类中直接定义没有任何修饰符、前缀、后缀的代码块即为构造代码块。我们明白一个类必须至少有一个构造函数,构造函数在生成对象时被调用。构造代码块和构造函数一样同样是在生成一个对象时被调用

public class Test{
{
System.out.println("我是构造代码块");
}
}

注意:

  • 构造代码块的作用是给对象初始化。
  • 对象一建立就调用构造代码块了,而且优于构造函数执行。这里强调一下,有对象创建,才会执行构造代码块,类不能调用构造代码块的,而且构造代码块与构造函数的执行顺序是前者先于后者执行。
  • 构造代码块与构造函数的区别是:构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化,因为构造函数是可以多个的,运行哪个构造函数就会建立什么样的对象,但无论建立哪个对象,都会先执行相同的构造代码块。也就是说,构造代码块中定义的是不同对象共性的初始化内容。

  

3、静态代码块:

想到静态我们就会想到static,静态代码块就是用static修饰的用{}括起来的代码段,它的主要目的就是对静态属性进行初始化。

public class Test {
static{
System.out.println("静态代码块");
}
}

  

注意:

  • 静态代码块随着类的加载而执行,而且只会执行一次,并优于主函数。具体说静态代码块由类调用,类调用时先执行静态代码块,然后才执行主函数。
  • 静态代码块是给类初始化的,而构造代码块是给对象初始化的。
  • 静态代码块中的变量是局部变量,和普通方法中的局部变量没有区别。
  • 一个类中可以有多个静态代码块。

三、Java类的初始化顺序

1、一个类的情况:

A:

public class Test {

	public Test(){
System.out.println("Test构造函数");
} {
System.out.println("Test构造代码块");
} static {
System.out.println("静态代码块");
} public static void main(String[] args) { } }

  

结果:

静态代码块

  

B:

public class Test {

	public Test(){
System.out.println("Test构造函数");
} {
System.out.println("Test构造代码块");
} static {
System.out.println("静态代码块");
} public static void main(String[] args) {
Test t=new Test();//创建了一个对象 } }

  

这段代码相比于上述代码多了一个创建对象的代码

结果:

静态代码块
Test构造代码块
Test构造函数

  

C:

public class Test {

	public Test(){
System.out.println("Test构造函数");
} {
System.out.println("Test构造代码块");
} static {
System.out.println("静态代码块");
} public static void main(String[] args) {
Test t1=new Test();//创建了一个对象 Test t2=new Test(); } }

  

结果:

静态代码块
Test构造代码块
Test构造函数
Test构造代码块
Test构造函数

  

由此结果可以看出:静态代码块只会在类加载的时候执行一次,而构造函数和构造代码块则会在每次创建对象的都会执行一次

对于一个类而言,按照如下顺序执行:

  1. 执行静态代码块
  2. 执行构造代码块
  3. 执行构造函数

对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。

D:

public class Test {

	//静态变量
public static String staticField="静态变量"; //变量
public String field="变量"; //静态初始化块
static {
System.out.println(staticField);
System.out.println("静态初始化块");
} {
System.out.println(field);
System.out.println("初始化块");
} //构造函数
public Test() {
System.out.println("构造函数");
} public static void main(String[] args) {
Test t=new Test();
} }

  

结果:

静态变量
静态初始化块
变量
初始化块
构造函数

  

2、继承情况下的代码执行顺序:

class TestA{
public TestA() {
System.out.println("A的构造函数");
} {
System.out.println("A的构造代码块");
} static {
System.out.println("A的静态代码块");
}
} public class TestB extends TestA { public TestB() {
System.out.println("B的构造函数");
} {
System.out.println("B的构造代码块");
} static {
System.out.println("B的静态代码块");
} public static void main(String[] args) {
TestB t=new TestB();
} }

  

这里有两个类,属于继承的关系,读者先不要看答案,自己思考一下结果是啥?

 A的静态代码块
B的静态代码块
A的构造代码块
A的构造函数
B的构造代码块
B的构造函数

结果

当设计到继承时,代码的执行顺序如下:

1、执行父类的静态代码块,并初始化父类的静态成员

2、执行子类的静态代码块,并初始化子类的静态成员

3、执行父类的构造代码块,执行父类的构造函数,并初始化父类的普通成员变量

4、执行子类的构造代码块,执行子类的构造函数,并初始化子类的普通成员变量

Java初始化流程图:

class Parent {
/* 静态变量 */
public static String p_StaticField = "父类--静态变量";
/* 变量 */
public String p_Field = "父类--变量";
protected int i = 9;
protected int j = 0;
/* 静态初始化块 */
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
/* 初始化块 */
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
} /* 构造器 */
public Parent() {
System.out.println("父类--构造器");
System.out.println("i=" + i + ", j=" + j);
j = 20;
}
} public class SubClass extends Parent {
/* 静态变量 */
public static String s_StaticField = "子类--静态变量";
/* 变量 */
public String s_Field = "子类--变量";
/* 静态初始化块 */
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
/* 初始化块 */
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
} /* 构造器 */
public SubClass() {
System.out.println("子类--构造器");
System.out.println("i=" + i + ",j=" + j);
} /* 程序入口 */
public static void main(String[] args) {
System.out.println("子类main方法");
new SubClass();
}
}

  

结果:

父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
子类main方法
父类--变量
父类--初始化块
父类--构造器
i=9, j=0
子类--变量
子类--初始化块
子类--构造器
i=9,j=20

  

(1)访问SubClass.main(),(这是一个static方法),于是装载器就会为你寻找已经编译的SubClass类的代码(也就是SubClass.class文件)。在装载的过程中,装载器注意到它有一个基类(也就是extends所要表示的意思),于是它再装载基类。不管你创不创建基类对象,这个过程总会发生。如果基类还有基类,那么第二个基类也会被装载,依此类推。

(2)执行根基类的static初始化,然后是下一个派生类的static初始化,依此类推。这个顺序非常重要,因为派生类的“static初始化”有可能要依赖基类成员的正确初始化。

(3)当所有必要的类都已经装载结束,开始执行main()方法体,并用new SubClass()创建对象。

(4)类SubClass存在父类,则调用父类的构造函数,你可以使用super来指定调用哪个构造函数。基类的构造过程以及构造顺序,同派生类的相同。首先基类中各个变量按照字面顺序进行初始化,然后执行基类的构造函数的其余部分。

(5)对子类成员数据按照它们声明的顺序初始化,执行子类构造函数的其余部分。

Java基础系列5:Java代码的执行顺序的更多相关文章

  1. 【Java多线程系列四】控制线程执行顺序

    假设有线程1/线程2/线程3,线程3必须在线程1/线程2执行完成之后开始执行,有两种方式可实现 Thread类的join方法:使宿主线程阻塞指定时间或者直到寄生线程执行完毕 CountDownLatc ...

  2. Go基础系列:指定goroutine的执行顺序

    Go channel系列: channel入门 为select设置超时时间 nil channel用法示例 双层channel用法示例 指定goroutine的执行顺序 当关闭一个channel时,会 ...

  3. 【Java基础系列】Java IO系统

    前言 创建好的输入/输出系统不仅要考虑三种不同种类的IO系统(文件,控制台,网络连接)还需要通过大量不同的方式与他们通信(顺序,随机访问,二进制,字符,按行,按字等等). 一.输入和输出 Java的I ...

  4. 【Java基础】构造方法 static 块 {}块 执行顺序

    package com.test.innerclass; public class HelloB extends HelloA { public HelloB() { System.out.print ...

  5. 夯实Java基础系列7:一文读懂Java 代码块和执行顺序

    目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...

  6. 夯实Java基础系列7:Java 代码块和执行顺序

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  7. Java基础系列-ArrayList

    原创文章,转载请标注出处:<Java基础系列-ArrayList> 一.概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. ...

  8. Java基础系列-Collector和Collectors

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748925.html 一.概述 Collector是专门用来作为Stream的coll ...

  9. Java基础系列--HashMap(JDK1.8)

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10022092.html Java基础系列-HashMap 1.8 概述 HashMap是 ...

随机推荐

  1. MongoDB 走马观花(全面解读篇)

    目录 一.简介 二.基本模型 BSON 数据类型 分布式ID 三.操作语法 四.索引 索引特性 索引分类 索引评估.调优 五.集群 分片机制 副本集 六.事务与一致性 一致性 小结 一.简介 Mong ...

  2. Windows下如何调试驱动程序

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 一.配置Windbg使用双机调试 win10中“windbg+vm ...

  3. 如何去除CFormView的Scrollbar

    第一种方法: 重载 OnSize(UINT nType, int cx, int cy) 在CFormView::OnSize(nType, cx, cy)下面添加一句 ShowScrollBar(S ...

  4. bugku 一个普通的压缩包

    压缩包打不开,用winhex打开压缩包,发现头文件是zip的,将后缀改为zip,成功解压. 打开发现还是个压缩包,而且打不开,提示secret.png损坏,使用winhex打开. 将a8 3c 7a ...

  5. Mybatis入门简版(补充)

    一.Mybatis 中$与#的区别 #相当于对数据 加上 双引号,$相当于直接显示数据 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#, ...

  6. vue中 props 多层组件嵌套传值

    如:三层嵌套. 父组件=>子组件=>孙子 1. 父组件引用子组件component11 , isShow传值给子组件component11 2. 子组件用  props 接受父组件的值, ...

  7. Oracle注入之带外通信

    Oracle注入之带外通信和DNSLOG注入非常相似,例如和mysql中load_file()函数实现无回显注入非常相似. 下面介绍这个技术中常用的函数和使用. 环境这里准备两台测试,一台注入点的靶机 ...

  8. 某PHP发卡系统SQL注入

    源码出自:https://www.0766city.com/yuanma/11217.html 安装好是这样的 审计 发现一处疑似注入的文件 地址:/other/submit.php 看到这个有个带入 ...

  9. windows 7 专业版 64位 无法安装.Net 4.7版本解决方案

    什么暂停windows update,改文件夹,再恢复windows update等等方法都试了,不行之后就觉得这才是终极解决方案. 不管你是win 7什么版本,你只需要下载安装对应系统的Window ...

  10. 使用oracle脚本生成VO和Dao

    话不多说直接上代码. 生成VO的脚本: SELECT '/**' || T2.COMMENTS || '*/ @Column(name="' || T1.COLUMN_NAME || '&q ...