46从零开始学Java之静态代码块和静态类、静态导入 ゝ一世哀愁。 2024-03-16 23:23 24阅读 0赞 > **作者**:孙玉昌,昵称【**一一哥**】,另外【**壹壹哥**】也是我哦 > > 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 ## 前言 ## 在上一篇文章中,**壹哥**给大家讲解了static静态关键字,以及静态变量、静态常量和静态方法等内容。但是关于static,还有其他的一些内容,比如静态类、静态代码块和静态导入等,接下来**壹哥**给大家继续分析讲解。我们一起来看看这些内容都是怎么用吧。 \-------------------------------------------------**前戏已做完,精彩即开始**\----------------------------------------------- 全文大约【**3300】**字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,可以让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考...... ## 配套开源项目资料 ## > **Github:** > > [GitHub - SunLtd/LearnJava][GitHub - SunLtd_LearnJava] > > **Gitee:** > > [一一哥/从零开始学Java][Java] ## 一. 静态代码块 ## ### 1. 概念 ### 由static修饰的代码块称为静态代码块,每个类中可以有多个静态代码块,每个静态代码块都只会在类加载时执行一次。对那些只需要进行一次操作的初始化代码,就可以放在静态代码块中执行。静态代码块具有如下特性: > * **静态代码块类似于是一个方法,但它不可以在方法中调用,也不能存在于任何方法体中;** > * **静态代码块可以写在类中的任何地方,一个类中也可以有多个静态代码块;** > * **静态代码块在类加载时执行;** > * **静态代码块优先于动态代码块执行;** > * **如果类中包含多个静态代码块,则JVM虚拟机会按它们在类中出现的先后顺序依次执行,每个静态代码块只会被执行一次;** > * **静态代码块与静态方法一样,不能直接访问类的实例变量和实例方法,需要通过类的实例对象来访问。** ### 2. 语法 ### 静态代码块的语法格式如下: static { //代码内容 } 静态代码块的语法格式比较奇特,static关键字后面直接跟一个\{ \}花括号,这就是静态代码块。我们可以在这个静态代码中编写若干代码,效果类似于是一个方法。 ### 3. 案例 ### #### 3.1 定义User类 #### 我们先来定义一个User类,在该类中定义一个静态代码块,一个非静态代码块,还有一个构造方法。在Java中,按照代码执行时间的早晚: > **静态代码块 > 非静态代码块 > 构造方法 > 普通方法** 我们要记住以下几点: > * **静态代码块,在类被加载时就会自动调用,且只会被调用一次。** > * **非静态代码块,在对象被创建时自动调用,每次创建对象时都会执行。** > * **而构造方法,每创建一个对象就会执行一次。** /** * @author 一一哥Sun */ public class User { //静态属性,属于整个类,被整个类的所有对象共享! static int num = 10; //普通属性,属于某个对象,是对象私有的! private int age=20; //静态代码块,在类被加载时自动调用,且只会被调用一次。比普通代码块先执行! static { //无论创建几个User对象,本静态代码块都只会执行一次,num++变成11 System.out.println("这是静态代码块,num="+(num++)); } //非静态代码块,在对象被创建时自动调用,每次创建对象时都会执行,比构造方法先执行! { //每创建一个User对象,就会执行一次本代码块,num++变成12,age=20. System.out.println("这是非静态代码块,num="+(num++)+",age="+(age++)); } //构造方法 public User(){ //每创建一个User对象,就会执行一次构造方法,num++变成13,age=21. System.out.println("这是无参构造方法,num"+(num++)+",age="+(age++)); } } #### 3.2 定义测试类 #### 接下来我们再定义一个测试类,在这里创建3个User对象。 /** * @author 一一哥Sun */ public class UserTest { public static void main(String[] args) { //创建第一个User对象 User user1=new User(); //创建第2个User对象 User user2=new User(); //创建第3个User对象 User user3=new User(); } } #### 3.3 执行结果分析 #### 上面的代码执行结果如下图所示: ![6f990385ffbc70336d457fb61de69182.png][] 在上述代码中,我们创建了3个User对象。其中,无论构造几次对象,一个类中的一个static静态代码块都只会执行一次,所以在构造第一个User对象时num是10。然后执行非静态代码块,num变成11,age等于20。接着执行构造方法。num=12,age=21。 之后开始构造第2个对象,此时只执行非静态代码块和构造方法,不会再执行静态代码块。因为num是静态属性,所以第2个user对象继续共享num变量,num=13;而因为age是成员变量,所以age是一个新的成员变量,age仍然是20。接着执行构造方法,num=14,age=21。 最后创建第3个User对象,过程和上述一样。 ### 4. 配套视频 ### 与本节内容配套的视频链接如下: [Bilibili External Player][] ## 二. 静态内部类 ## ### 1. 概念 ### 在Java中,**我们可以在一个类的内部定义另一个类,也就是A类里面可以嵌套一个B类,这个内部的B类就叫做内部类。而内部类根据是否带有static关键词,可以分为静态内部类和非静态内部类。** 其中,静态内部类使用 static关键字修饰。对于静态内部类,我们可以直接访问,不需要创建外部类来访问它。 注意,对于内部类,**壹哥**会在后面进行专门的讲解,所以此处我们大家先有个印象即可。 ### 2. 语法 ### 静态内部类的语法格式如下: public class 外部类 { //代码... static class 内部类{ //代码... } } ### 3. 案例 ### #### 3.1 定义静态内部类 #### 这里**壹哥**先简单定义一个静态内部类,后面我们在学习内部类时再专门讲解。在这个静态内部类中,**壹哥**定义了一个方法,来访问外部类中的普通属性和静态属性。我们要记住以下几点: > * **静态内部类访问外部类的成员变量时,需要先创建外部类对象;** > * **非静态内部类可以直接访问使用外部类的成员变量,如同使用本类中的变量;** > * **所有的内部类访问外部类的静态变量时,可以直接通过"外部类.静态变量"的形式访问。** /** * @author 一一哥Sun * 外部类和内部类 */ public class OuterClass { //普通属性,属于外部类 static int outerNum=10; //定义一个静态的内部类,如果不带static,就是一个普通的内部类。 //内部类的使用,和普通类一样,里面可以正常定义属性、方法、构造方法等。 static class InnerClass{ //私有属性无法在类的外部直接访问 //private int innerNum=20; int innerNum=20; public void printNum() { //定义外部类对象 OuterClass outer=new OuterClass(); //这里的this是指InnerClass内部类对象! System.out.println("innerNum="+this.innerNum+",outerAge="+outer.outerAge+",outerNum="+OuterClass.outerNum); } } } #### 3.2 定义测试类 #### 我们再定义一个测试类,看看内部类对象是怎么调用的。 /** * @author 一一哥Sun * 测试访问内部类 */ public class InnerClassTest { public static void main(String[] args) { //创建内部类对象,格式为“外部类.内部类 对象名 = new 外部类.内部类的构造方法” OuterClass.InnerClass inner = new OuterClass.InnerClass(); //调用内部类的方法 inner.printNum(); //访问外部类属性 System.out.println("outerNum="+OuterClass.outerNum); //访问内部类属性 System.out.println("innerNum="+inner.innerNum); } } ## 三. 静态导入 ## ### 1. 概念 ### JDK 1.5之后,Java中新增了一种**静态导入的语法,用于导入指定类中的某个静态变量、静态方法或全部的静态变量和静态方法****。**如果一个类中的方法全都是使用 static 声明的静态方法,我们就可以通过import static的方式进行导入,这种导包方式就叫做静态导入。 ### 2. 语法 ### 我们要使用import static语句进行静态导入,根据导入数量的多少,会有两种情况: > * **部分导入:导入部分静态变量或静态方法;** > * **全部导入:导入全部静态变量或静态方法。** #### 2.1 部分导入 #### 部分导入是指利用静态导入的语法,导入指定类中单个的静态变量或静态方法。语法格式如下: import static package.ClassName.fieldName|methodName; package要导入的包名,ClassName类名,fieldName是静态变量名或methodName静态方法名。 #### 2.2 全部导入 #### 全部导入是指利用静态导入的语法,导入指定类中全部的静态变量或静态方法。语法格式如下: import static package.ClassName.*; 上面的星号是java中的一种通配符,代表所有导入的静态变量或静态方法名。 我们要注意,import static语句要放在Java代码的 package 语句之后、类定义之前,与普通的import语句平级。 ### 3. 案例 ### **壹哥**在这里设计一个简单的案例,给大家演示一下静态导入的使用。我们之前进行输出的时候,经常使用`System.out.println("");`语句,其实这样就挺麻烦,每次都要写`System.out`,实际上我们只需要调用println()方法就可以了。而println()就是一个静态方法,所以我们就可以使用静态导包来简化操作了。 package com.yyg.staticdemo; //静态导入System类中的所有静态成员 import static java.lang.System.*; //静态导入Math类中的所有静态成员 import static java.lang.Math.*; /** * @author 一一哥Sun * 静态导包案例 */ public class StaticImportDemo { public static void main(String[] args) { //System.out.println("静态导包"); //out其实是java.lang.System类的静态变量,表示标准输出; //PI是java.lang.Math类中的静态变量,表示数学里的π常量; //java.lang.Math.PI out.println(PI); //我们可以直接调用Math类的sqrt静态方法,返回64的正平方根 //java.lang.Math.sqrt(E) out.println(sqrt(64)); } } \------------------------------------------------**正片已结束,来根事后烟**\---------------------------------------------- ## 四. 结语 ## 至此,**壹哥**就把static静态变量、静态常量、静态代码块、静态类、静态导入等相关的内容给大家全部介绍完毕了。这些都是我们开发时很常用的内容,所以**壹哥**希望各位初学者,要把static相关的内容牢牢掌握。最后**壹哥**再来给大家简单总结一下本文要点: > * **静态成员属于所有实例对象都“共享”的字段,是****类****中的“公共财产”;** > * **调用静态方法不需要实例对象,静态方法中不能使用****this和super****;** > * **静态方法中可以访问静态变量和其他静态方法;** > * **静态方法一般是在工具类中定义;** > * **掌握静态代码块的写作方式;** > * **掌握静态内部类的调用方式;** > * **掌握静态导入的使用方式。** 另外如果你独自学习觉得有很多困难,可以加入**壹哥**的学习互助群,大家一起交流学习。 ## 五. 今日作业 ## ### 1. 第一题 ### //父类 class Super{ public static void m1(){ System.out.println("m1inSuper"); } public void m2(){ System.out.println("m2inSuper"); } } //子类 class Sub extends Super{ public static void m1(){ System.out.println("m1inSub"); } public void m2(){ System.out.println("m2inSub"); } } //测试类 public class TestMain{ public static void main(String args[]){ Super sup=new Sub(); sup.m1(); sup.m2(); Sub sub=(Sub)sup; sub.m1(); sub.m2(); } } 写出上述代码的执行结果,请在评论区给出你的答案。 [GitHub - SunLtd_LearnJava]: https://github.com/SunLtd/LearnJava [Java]: https://gitee.com/sunyiyi/LearnJava [6f990385ffbc70336d457fb61de69182.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/40cd8ff6d4a94093b184a23bfa0c4c4a.png [Bilibili External Player]: https://player.bilibili.com/player.html?bvid=BV1Ja411x7XB&p=83&page=83
还没有评论,来说两句吧...