简述网站建设及维护的全过程,wordpress 多语言 切换,东营市建设信息网官网,网站建设名词解释与简答题概述 : 特点 : 格式 : 情景 : 细节 : 演示 : 英文 : //v#xff0c;新版编辑器无手动添加目录的功能#xff0c;PC端阅读建议通过侧边栏进行目录跳转#xff1b;移动端建议用PC端阅读。#x1f602;一、概述 :代码块#xff0c;也称为初始化块#xff0c;属于类中的成员v新版编辑器无手动添加目录的功能PC端阅读建议通过侧边栏进行目录跳转移动端建议用PC端阅读。一、概述 :代码块也称为初始化块属于类中的成员即和属性方法一样是类的一部分。代码块的形成如同方法一样用花括号将一些代码包括起来。只不过相比方法来看代码块只有方法体。二、特点 :与方法相比代码块没有返回值类型没有方法名也没有形参列表是个名副其实的“三无方法”。代码块只有方法体而且在调用时不需要通过创建对象或是像使用类方法那样显式的调用而是在加载包含代码块的类时或者是在实例化该类对象时自动的隐式调用。大家可以想象一下蛞蝓和蜗牛在形态上的区别。如下图所示如果说代码块就是蛞蝓[kuò yú]只有身体没有框架那么方法就相当于是蜗牛既有框架来收容这个身体身体本身的功能也正常。当然就像蛞蝓和蜗牛都是害虫一样代码块和方法也有自己的共同点平时在方法中会写到的任意类型的语句都可以根据需求写在代码块中。三、格式 : [修饰符] { //方法体语句。代码}PS : (对格式的补充说明对于代码块前面的修饰符可以不写但你要是想写的话只能使用static关键字来修饰。根据代码块是否有static修饰可以将代码块分为非静态代码块无static修饰和静态代码块添加了static修饰符。这是本质上的区别代码块最后的分号“;”可写可不写但是建议大家写上以示区分。四、情景 : 说了这么一大堆到底啥时候要用代码块呢前面我们说了代码块并不能显式调用而是在加载类或者实例化类时隐式地调用。其实在我们后面的使用细节中就会说到——静态代码块是随着类的加载而被隐式调用非静态代码块则是随着类的实例化而被隐式调用。大家先了解一下因为要给大家举个例子所以up先提一嘴后面我们会细说。当多个构造器中有重复的代码片段时我们就可以将这些重复的相同代码提取出来放在一个非静态代码块中这样每次创建一个该类对象都会隐式地调用一次代码块就不用你在每个构造器中都写一遍了大大提高了代码的复用性。下面我们来举个例子 : up以Rocket类火箭类为演示类以Test类为测试类我们在Rocket类中定义一个无参构造和两个带参构造并使其都包含一段相同的代码段(模拟火箭发射的代码段)。老规矩因为演示嘛为了观感简洁up将Test类写在了Rocket类的源文件下。Rocket类Test类代码如下 : package knowledge.polymorphism.code_block;public class Rocket {public Rocket() {System.out.println(火箭发射倒计时Come on );System.out.println(10!);System.out.println(9!);System.out.println(8!);System.out.println(7!);System.out.println(6!);System.out.println(5!);System.out.println(4!);System.out.println(3!);System.out.println(2!);System.out.println(1!);System.out.println(0发射奥利给);System.out.println(---------------------);System.out.println(火箭发射成功无参构造被掉用啦);}public Rocket(String name) {System.out.println(name 火箭发射倒计时Come on );System.out.println(10!);System.out.println(9!);System.out.println(8!);System.out.println(7!);System.out.println(6!);System.out.println(5!);System.out.println(4!);System.out.println(3!);System.out.println(2!);System.out.println(1!);System.out.println(0发射奥利给);System.out.println(---------------------);System.out.println(name 火箭发射成功第一个有参构造被调用啦);}public Rocket(String name, String time) {System.out.println(name 火箭发射倒计时Come on );System.out.println(10!);System.out.println(9!);System.out.println(8!);System.out.println(7!);System.out.println(6!);System.out.println(5!);System.out.println(4!);System.out.println(3!);System.out.println(2!);System.out.println(1!);System.out.println(0发射奥利给);System.out.println(---------------------);System.out.println(name 火箭在 time 发射成功第二个有参构造被调用啦);}
}class Test {public static void main(String[] args) {//利用无参构造创建火箭类对象Rocket rocket_1 new Rocket();System.out.println();//利用第一个有参构造创建火箭类对象Rocket rocket_2 new Rocket(神舟99号);System.out.println();//利用第二个有参构造创建火箭类对象Rocket rocket_3 new Rocket(长征99号, 2077.10.1_8:34:50);}
}运行效果如下GIF图 : 大家发现没有三个构造器中都有表示火箭倒计时的代码使我们的代码冗余度很高看起来臃肿不堪导致代码的复用性差。这时候我们可以将表示火箭倒计时的代码提取出来放到一个非静态代码块中。这样不管你用哪个构造器来创建该类对象只要你实例化了该类每实例化一次都会默认隐式地调用非静态代码块中的内容。更改后的代码如下所示 : package knowledge.polymorphism.code_block;public class Rocket {{System.out.println(火箭发射倒计时Come on );System.out.println(10!);System.out.println(9!);System.out.println(8!);System.out.println(7!);System.out.println(6!);System.out.println(5!);System.out.println(4!);System.out.println(3!);System.out.println(2!);System.out.println(1!);System.out.println(0发射奥利给);System.out.println(---------------------);};public Rocket() {System.out.println(火箭发射成功无参构造被掉用啦);}public Rocket(String name) {System.out.println(name 火箭发射成功第一个有参构造被调用啦);}public Rocket(String name, String time) {System.out.println(name 火箭在 time 发射成功第二个有参构造被调用啦);}
}class Test {public static void main(String[] args) {//利用无参构造创建火箭类对象Rocket rocket_1 new Rocket();System.out.println();//利用第一个有参构造创建火箭类对象Rocket rocket_2 new Rocket(神舟99号);System.out.println();//利用第二个有参构造创建火箭类对象Rocket rocket_3 new Rocket(长征99号, 2077.10.1_8:34:50);}
}运行结果不变如下GIF所示 : 五、细节 : 1.静态代码块的作用是对整个类进行初始化工作且随着类的被加载而被隐式地调用。由于一个类的字节码文件只会被加载一次因此静态代码块也最多只能被执行一次。而对于非静态代码块来说每创建一个包含非静态代码块的类 (即每实例化一次该类)都会执行一次该类中的非静态代码块。注意如果仅仅通过“类名.”的形式去调用类的静态成员即类变量和类方法的使用那么非静态代码块不会执行。2.关于类的加载和类的加载时机up在之前的java 反射基础 万字详解中已经讲过大家有兴趣的话可以去看看直接在目录中找到类加载部分即可。这里up给大家把截图放过来,如下 :3.关于在创建对象时静态成员、非静态成员以及构造器在一个类中的调用顺序 : ①首先执行静态代码块(因为要加载类)和静态属性的初始化这两者的执行优先级相同同级。但如果同时定义了多个静态代码块和多个静态属性的初始化语句则按照定义的顺序来执行。即谁在前头先执行谁②其次执行非静态代码块和非静态属性的初始化这两者的执行优先级也相同同级。同理若同时定义了多个非静态代码块和多个非静态属性的初始化语句则按照定义的先后顺序来执行。③最后执行构造器初始化。4.为什么是上面第三点提到的这个顺序我们知道构造器的最前面默认隐含一条super(); 语句其实在super();语句后面还隐含了调用非静态代码块的语句。所以这就能解释为什么是第三点注意提到的顺序了——静态成员静态代码块静态属性的初始化在类加载器加载该类时就已经执行完毕了所以它们是第一优先级而由于构造器中隐含了调用非静态代码块的语句因此必须先执行完毕非静态代码块才能继续执行构造器。5.在继承关系的基础上创建子类对象时静态成员、非静态成员以及构造器在子父类中的调用顺序多层继承也适用①首先执行父类的静态代码块和静态属性初始化语句。(若同时定义了多个因为优先级同级按照定义的先后顺序执行)②其次执行子类的静态代码块和静态属性初始化语句。同上③接着执行父类的非静态代码块和非静态属性初始化。同上④接着执行父类构造器。⑤接着执行子类的非静态代码块和非静态属性初始化。同上⑥最后执行子类构造器。为什么在上文”类的加载时机“中我们谈到——初始化类的子类时要先加载父类而类的静态代码块和静态属性的初始化是随着类的加载而执行完毕的。因此当创建子类对象时第一步是执行父类的静态代码块和静态属性初始化第二步才是执行子类的静态代码块和静态属性初始化。当子类和父类都加载成功后jvm要根据你创建子类对象时传入的参数去找子类中对应的构造器但是别忘了——之前我们讲到继承关系时我们说过继承关系中对象的初始化顺序为 : 先初始化父类内容后初始化子类内容。所以会先通过子类的super语句来到父类的构造器而父类构造器又隐含了调用父类非静态代码块的语句而且我们在创建对象的内存图解中也讲过对象属性的初始化有三步默认初始化显式初始化构造器初始化。因此第三步是执行父类的非静态代码块和非静态属性初始化第四步才是执行父类的构造器。父类内容初始化完成后返回子类构造器中子类构造器也隐含了调用子类非静态代码块的语句因此第五步是执行子类的非静态代码块和非静态属性初始化第六步才是执行子类构造器。至此一个子类对象创建完毕。6.在讲到static关键字时我们说过静态成员只能调用静态成员类变量和类方法而非静态成员既能调用静态成员也能调用非静态成员。文章开篇我们就说了代码块不也是类的成员么因此静态代码块只能调用静态成员类变量类方法而非静态代码块可以调用任意成员。六、演示 : 1.演示细节1 : up以Cat类为演示类以TestDetial_1作为第一个测试类。我们在Cat类中定义一个静态代码块和一个非静态代码块。通过在测试类中创建多个Cat类对象来观察两种代码块的执行次数各有什么特点。Cat类TestDetail_1类代码如下 : package knowledge.polymorphism.code_block.chinese.detail_1;
/*//细节1 :静态代码块的作用是对整个类进行初始化工作且随着类的被加载而被隐式地调用。由于一个类的字节码文件只会被加载一次因此静态代码块也最多只能被执行一次。而对于非静态代码块来说每创建一个包含非静态代码块的类 (即每实例化一次该类)都会执行一次该类中的非静态代码块。注意如果仅仅通过“类名.”的形式去调用类的静态成员即类变量和类方法的使用那么非静态代码块不会执行。*/
public class Cat {{System.out.println(这是Cat类中的非静态代码块捏);System.out.println(非静态代码块随着类的实例化而执行每实例化一次类就执行一次);System.out.println();};static {System.out.println(这是Cat类中的静态代码块捏);System.out.println(静态代码块随着类的加载而执行仅执行一次);System.out.println();};public static String name 猫;public static void eat() {System.out.println(喜欢吃);}public Cat() {}
}
class TestDetail_1 {public static void main(String[] args) {//创建Cat类对象Cat cat_0 new Cat();Cat cat_1 new Cat();Cat cat_2 new Cat();}
}运行结果 : 2.演示细节2 : 细节2没啥演示的吧基本都继承那块儿的。这样给大家演示一下调用静态成员时类的加载情况吧如下 :up以Dog类为演示类以TestDetail_2类为第二个测试类。在Dog类中定义一个静态的dog()方法。然后在测试类中通过类名来调用这个类方法。观察该类的静态代码块是否执行。Dog类TestDetail_2类代码如下 : package knowledge.polymorphism.code_block.chinese.detail_2;public class Dog {static {System.out.println(这是Dog类的静态代码块如果Dog类被加载那么这句话一定输出);System.out.println(------------------------------------);};//定义Dog类的静态方法类方法public static void dog() {System.out.println(我虽然不是人但你是真的。);}
}class TestDetail_2 {public static void main(String[] args) {//以类名的形式调用Dog类中的类方法Dog.dog();}
}运行结果 : 3.演示细节3 : up以Fish类为演示类以TestDetail_3类为第三个测试类。在Fish类中定义静态代码块静态属性使用静态方法给静态属性赋初值非静态代码块非静态属性通过非静态方法给非静态属性赋初值以及一个Fish类的空参构造。在每个成员中均打印出提示信息。在测试类中创建Fish类对象观察Fish类中各个成员的执行顺序。Fish类TestDetail_3类代码如下 : package knowledge.polymorphism.code_block.chinese.detail_3;
/*//细节3 :①首先执行静态代码块(因为要加载类)和静态属性的初始化这两者的执行优先级相同同级。但如果同时定义了多个静态代码块和多个静态属性的初始化语句则按照定义的顺序来执行。即谁在前头先执行谁②其次执行非静态代码块和非静态属性的初始化这两者的执行优先级也相同同级。同理若同时定义了多个非静态代码块和多个非静态属性的初始化语句则按照定义的先后顺序来执行。③最后执行构造器初始化。
*/
public class Fish {//Fish类的代码块{System.out.println(这是Fish类的非静态代码块);System.out.println(非静态代码块的执行处于第二优先级因此这句话是第二阶段输出);};static {System.out.println(这是Fish类的静态代码块);System.out.println(静态代码块的优先级是最高的所以这句话必须第一阶段输出。);};//Fish类构造器public Fish() {System.out.println(最后输出的就是Fish类的构造器这是第三阶段输出。);}//Fish类静态属性及其初始化public static String name getName();public static String getName() {System.out.println(静态属性的初始化与静态代码块的执行为相同优先级。所以也是第一阶段输出);System.out.println(只不过此处静态属性定义的位置靠后一点点所以这句话输出稍微靠后。);System.out.println(------------------------------------------------);return 鱼;}//Fish类非静态属性及其初始化public String hobby getHobby();public String getHobby() {System.out.println(非静态属性的初始化和非静态代码块相同优先级。);System.out.println(只不过由定义的先后顺序来看这句话要在非静态代码块之后才能输出。);System.out.println(------------------------------------------------);return 鱼能有啥爱好喜欢游泳;}
}class TestDetail_3 {public static void main(String[] args) {//创建Fish类对象看看各个阶段的输出内容分别是个啥。Fish fish new Fish();System.out.println(fish.hobby);}
}运行结果 : 4.演示细节4 : up以Fruit类为父类子类Apple类继承了Fruit类以TestDetail_4类为第四个测试类。在子父类中均定义一个无参构造和一个非静态代码块。通过控制台打印出的信息观察执行规律。Fruit类Apple类TestDetail_4类代码如下 : package knowledge.polymorphism.code_block.chinese.detail_4;
/*//细节4 :构造器的最前面默认隐含一条super(); 语句其实在super();语句后面还隐含了调用非静态代码块的语句。*/
public class Fruit {{System.out.println(Fruit类的非静态代码块。);};public Fruit() {//super(); 父类构造器中其实也隐含了supper语句只不过顶层父类Object类中不会输出内容。//supper语句之后隐含了调用本类非静态代码块的语句。System.out.println(这是父类构造器);}
}
class Apple extends Fruit {{System.out.println(Apple类的非静态代码块。);};public Apple() {//super();//实质这里还隐含了调用本类非静态代码块的语句。System.out.println(这是子类构造器。);}
}class TestDetail_4 {public static void main(String[] args) {Apple apple new Apple();}
}运行结果 : 我们之前说过对于非静态代码块每实例化一次类就执行一次。通过输出结果可以看到尽管我们创建的是子类对象但因为super语句调用父类构造器而父类构造器中隐含调用非静态代码块的语句。因此最后输出的内容中会先输出父类的非静态代码块。5.演示细节5 : up以Fruit类水果类为父类子类Apple类苹果类继承Fruit类子类的子类HongFuShi类红富士类继承Apple类;以TestDetail_5为第五个测试类。在三个类中均定义静态代码块静态属性非静态代码块非静态属性以及构造器。并在每个成员中给出提示信息。在测试类中创建红富士类对象根据控制台打印出的提示信息来Fruit类Apple类HongFuShi类代码如下 : package knowledge.polymorphism.code_block.chinese.detail_5;public class Fruit { //父类 : 水果类//Fruit类静态属性及其初始化private static String name getName();public static String getName() {System.out.println(1.这是父类Fruit类的静态方法用于初始化父类的静态属性。);return 水果;}//Fruit类的非静态属性及其初始化private String color getColor();public String getColor() {System.out.println(7.这是父类Fruit类的非静态方法用于初始化父类的非静态属性。);return 水果的颜色;}//Fruit类构造器空参public Fruit() {System.out.println(9.这是父类Fruit类的空参构造。);System.out.println(-------------------------------------);}//Fruit类的静态代码块和非静态代码块static {System.out.println(2.这是Fruit类的静态代码块);};{System.out.println(8.这是Fruit类的非静态代码块);};
}
class Apple extends Fruit { //子类 : 苹果类//Apple类静态属性及其初始化private static String name getName();public static String getName() {System.out.println(3.这是子类Apple类的静态方法用于初始化子类的静态属性。);return 苹果;}//Apple类的非静态属性及其初始化private String apple_color getApple_color();public String getApple_color() {System.out.println(10.这是子类Apple类的非静态方法用于初始化子类的非静态属性。);return 苹果的颜色;}//Apple类构造器空参public Apple() {System.out.println(12.这是子类Apple类的空参构造。);System.out.println(-------------------------------------);}//Apple类的静态代码块和非静态代码块static {System.out.println(4.这是Apple类的静态代码块);};{System.out.println(11.这是Apple类的非静态代码块);};
}
class HongFuShi extends Apple { //子类的子类 : 红富士类//HongFuShi类静态属性及其初始化private static String name getName();public static String getName() {System.out.println(5.这是最底层子类HongFuShi类的静态方法用于初始化最底层子类的静态属性。);return 红富士;}//HongFuShi类的非静态属性及其初始化private String HongFuShi_color getHongFuShi_color();public String getHongFuShi_color() {System.out.println(13.这是最底层子类HongFuShi类的非静态方法用于初始化最底层子类的非静态属性。);return 红色;}//HongFuShi类构造器空参public HongFuShi() {System.out.println(15.这是最底层子类HongFuShi类的空参构造。);System.out.println(-------------------------------------);}//HongFuShi类的静态代码块和非静态代码块static {System.out.println(6.这是HongFuShi类的静态代码块);System.out.println(-------------------------------------------);};{System.out.println(14.这是HongFuShi类的非静态代码块);};
}
class TestDetail_5 {public static void main(String[] args) {//创建一个红富士类对象。HongFuShi hongFuShi new HongFuShi();}
}运行结果 : 大家一开始理解起来有点难度是正常的。大家一定要记住每个构造器的第一行默认隐含super语句并且在super语句之后还默认隐含了调用非静态代码块的语句。可以说想要完全理解这一块知识点需要大家对Java 继承有不错的掌握程度。这里up再给大家捋一捋如下全文背诵 : ①首先你要创建最底层子类红富士类的对象肯定要先将该类的字节码文件加载到方法区但是加载时jvm发现红富士类继承了苹果类因此必须先加载苹果类的字节码文件但是加载时jvm又发现苹果类继承的水果类因此必须最先加载水果类的字节码文件。②好嘞我们知道静态代码块和静态属性的初始化是随着类的加载而执行完毕的。因此在加载水果类时会执行水果类的静态代码块和静态属性初始化。水果类加载完毕后就要返回去加载它的子类苹果类因此要顺势执行苹果类中的静态代码块和静态属性初始化。等爸爸和爷爷完事儿后这才轮到孙子红富士类也不敢耽搁兢兢业业赶紧加载jvm也顺势执行红富士类中的静态代码块和静态属性初始化。到此这三个类都加载完毕。③这时jvm会根据你创建红富士类对象时传入的形参列表去红富士类中找对应的构造器。但是刚找到构造器准备执行呢构造器第一行埋伏着默认的super语句立马被迫来到了苹果类没想到丫的苹果类也隐含默认语句super立马又被迫来到水果类继承机制要求我们要先将父类水果类进行初始化然而水果类的构造器第一行也有super语句但是水果类的父类就是顶层父类Object类了就不多说了。除去super语句外水果类的构造器中还隐含了调用水果类非静态代码块的语句且水果类中非静态属性的构造器初始化之前是显式初始化因此下一步是执行水果类的非静态代码块和非静态属性初始化。这些都后才能执行水果类的构造器。好不容易算是把父类初始化完毕这算是苹果类的super语句结束了。④接着又返回子类苹果类的构造器中super语句之后又隐藏了调用苹果类的非静态代码块的语句且苹果类非静态属性的构造器初始化之前要进行显式初始化因此下一步是执行苹果类的非静态代码块和非静态属性初始化。这些都后才能执行苹果类的构造器。这算是最底层子类红富士类的super语句结束了。与③同理⑤接着又返回最底层子类红富士类的构造器中super语句之后又隐藏了调用红富士类的非静态代码块的语句且红富士类非静态属性的构造器初始化之前要进行显式初始化因此下一步是执行红富士类的非静态代码块和非静态属性初始化。这些都后才能执行红富士类的构造器初始化红富士类对象。至此结束。与③同理6.演示细节6 : 其实细节6也没什么好演示的都是老生常谈的问题和之前讲到static修饰方法时一个道理。up以Student类作为演示类以TestDetail_6作为第六个测试类。在Student类中定义静态属性name和非静态属性age再定义静态方法getName() 和非静态方法getAge() 并分别定义静态代码块和非静态代码块去调用这些成员。在测试类创建Student类对象并查看输出结果。Student类TestDetail_6类代码如下 : package knowledge.polymorphism.code_block.chinese.detail_6;public class Student {private static String name Cyan;private int age 20;public static String getName() {return name;}public int getAge() {return age;}{System.out.println(name); //非静态代码块——可以调用静态成员System.out.println(age);System.out.println(name getName());System.out.println(age getAge()); //非静态代码块——也可以调用非静态成员};static {System.out.println(name); //静态代码块——只能调用静态成员//System.out.println(age); //这么写会报错。System.out.println(name getName());//System.out.println(age getAge()); //静态代码块——不可以调用非静态成员System.out.println(-----------------------------------);};
}
class TestDetail_6 {public static void main(String[] args) {Student student new Student();}
}运行结果 : 如果我们在Student类的静态代码块中调用非静态成员变量age或者是非静态成员方法getAge()IDEA就会报错如下图所示 : 七、英文其实up是先发的英文版本但没关系。英文版本适合英文六级及以上水平的小伙伴儿们阅读。up的英文版本都是拿英文重新描述的所举案例和描述思想都会不同而且up如果有写英文讲解java 的想法时一般都是先写英文版本再写中文版本不会存在单纯的翻译这一“拙劣行径”大家放心!好滴up把英文版本的代码块(Code Block) 详解链接给大家放下面了感谢阅读https://blog.csdn.net/TYRA9/article/details/128992057?spm1001.2014.3001.5501