Java: static,final,代码块 的详解

news/2024/5/2 19:08:07/文章来源:https://blog.csdn.net/weixin_61635597/article/details/128422808

Java: static,final,代码块 的详解

在这里插入图片描述


每博一文案

山本文绪说过这样一句话:哪些决定放弃了的事,就请放弃得干干净净。哪些决定再也不见面的人,就真
的不要再见面了,不要再做背叛自己的事,如果想要爱别人,就先好好爱自己。	
人生是一场有去无回的旅行,旧日种种,结成过往,我们只能回过头看,却不能从头走,好的也罢,坏的也罢,
过去的都已成定局了。不管是遗憾还是庆幸,都要带着这份烙印,继续走向漫漫人生。
正如那句极有名的禅语:无论你遇见谁,他都是对的人,无论发生什么事,那都是唯一会发生的事。
不管事情开始于那个时刻都是对的,时刻已经结束的,就是结束了。如果没有失去,就不会懂得珍惜。
但是你知道吗?如果已经失去了,就该学会放弃,没有什么是注定会属于我们的,得到或者失去,都是自有它的安排。
面对哪些注定要说再见到人或物,与其拼命拉扯,泪影婆娑,倒不如落落大方道一句“珍重”。
从从容容德告个别,然后留下一个潇洒离开的背影,从今以后更加坚定自己的路,将自己的人生过得有声有色。
愿你可饮最烈的酒,也能放开该放的手,从前不回头,往后强求。——————   一禅心灵庙语

文章目录

  • Java: static,final,代码块 的详解
    • 每博一文案
    • 1. static 关键字
      • 1.1 static 修饰属性
      • 1.2 static 修饰方法
      • 1.3 static 修饰代码块
      • 1.4 static 修饰内部类
      • 1.5 开发中如何合理的使用 staitc 关键字
    • 2. main 方法的探究
    • 3. 代码块
      • 3.1 程序中成员变量赋值的执行顺序
    • 4. final 关键字
    • 5. 总结:
    • 6. 最后:


1. static 关键字

当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上 的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象, 其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少 对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。这里我们就可以用到 static 关键字的使用了。

static : 表示的含义是 :静态的

在Java类当中, static 可以修饰属性,方法,代码块,内部类

1.1 static 修饰属性

static 修饰属性(变量): 按是否使用 static 修饰,可以分为为 静态属性(类属性) VS 非静态属性(实例属性)

非静态属性(实例属性): 我们创建了类的多个对象,每个对象都独立的拥有一套 类中的 非静态属性,非静态变量对应不同的实例对象(new) 自身的修改,不会影响到其他的 对象当中的一套非静态属性。

静态属性(类属性): 我们创建了类的多个对象,但是多个对象共享同一个静态属性,当通过某一个对象修改静态属性时,会导致其他对象调用此静态变量时,是最后一次修改过的结果。

被 static 修饰的属性的特点:

  • 静态属性随着类的加载而加载,早于 new 对象的加载创建,因为 new 对象,要先加载类,再调用类中的构造方法创建对应的对象。
  • 在访问权限允许的情况下,静态属性可以通过**“类名.静态属性名”** 的方式进行调用。
  • 由于类只会加载一次,则静态属性(静态变量) 在内存(方法区)当中也只会存在一份,存在方法区的静态域当中。
  • 静态属性有:System.out; Math.PI;
package blogs.blog2;public class StaticTest {public static void main(String[] args) {Chinese c1 = new Chinese();c1.nation = "CHN";Chinese c2 = new Chinese();c2.nation = "CHINA";System.out.println("c2.nation: "+c1.nation);System.out.println("c2.nation: "+c2.nation);// 可以通过 类名.静态属性 ()Chinese.nation = "中国";System.out.println("Chinese.nation: "+Chinese.nation);}
}class Chinese{String name;int age;static String nation;     // 被 static 修饰的静态属性}

在这里插入图片描述

在这里插入图片描述


1.2 static 修饰方法

被 staitc 修饰的方法,被称为是 ”静态方法“ 或者是 类方法。

静态方法的特点:

  • 同样静态方法也是和随着类的加载而加载到内存(方法区)当中的。
  • 在访问权限允许的情况下,静态属性可以通过**“类名.静态方法名”** 的方式进行调用。
  • 静态方法只能调用 静态的方法/属性 ,无法调用非静态的方法/属性,除非 实例化对象(new)。因为一个(静态方法)是已经在内存当中存在了的,调用一个(非静态的)还没有加载到内存当中的,JVM 是不允许的。
  • 在静态的方法内:不能使用 'this’关键字 以及 super 关键字,他俩都是表示对象的引用.
  • 非静态方法可以调用非静态方法或属性,也可以调用静态方法或属性。
  • 被 static 修饰的方法无法重写

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

在这里插入图片描述


package blogs.blog2;public class StaticTest {public static void main(String[] args) {// 静态方法可以直接使用  “类名.静态方法”调用Chinese.show();}
}class Chinese{String name;int age;static String nation;     // 被 static 修饰的静态属性public static void show(){System.out.println("我是静态方法");// name = "TOM";  // 静态方法无法直接调用非静态的属性// eat();   // 静态方法无法直接调用非静态的方法,可以通过 new 实例对象,调用/*this.name = "Tom";super.clone();*/  // 静态方法中无法使用 this./super.// 静态方法可以直接调用静态属性,静态方法nation = "Hello";   // 静态属性sleep();            // 静态方法}public void eat(){System.out.println("吃饭");System.out.println("***************************");// 非静态方法可以直接调用 静态方法/属性,因为加载内存的先后原因nation = "World";     // 静态属性sleep();              // 静态方法}public static void sleep() {System.out.println("睡觉");}
}

在这里插入图片描述


被 stiatic 修饰的方法,继承时,无法被重写,就算你按照重写的要求,编写好了没有报错,但是运行的时候,调用的是父类中没有被重写的方法 因为 stiatic 是类方法,和类一起加载到内存当中的,而多态中的重写是,运行时类型,只有运行了。才

package blogs.blog2;public class StaticTest {public static void main(String[] args) {Earth earth = new Chinese();  // 多态earth.human();}}class Chinese extends Earth{public static void human() {System.out.println("中国人");}
}class Earth{public static void human(){System.out.println("人类");}}

在这里插入图片描述


1.3 static 修饰代码块

被 static 修饰的代码块,被称为 “静态代码块”

具体详细,继续往下看,在 3.代码块 这一段有详细说明

1.4 static 修饰内部类

关于这一部分内容,大家可以移步至:🔜🔜🔜

1.5 开发中如何合理的使用 staitc 关键字

开发中:如何确定一个属性是否声明未 static ???

如果一个属性可以被多个对象共享的,不会随着对象不同而不同的,就可以声明为 staitc

一般 static 是和 final 一起修饰 变量的。

开发中:如何确定一个方法是否要声明为 static 的 ???

一般是 stiatic 的属性,通常对应的 set/get 方法也是 stiatic 的

工具类中的方法,习惯上声明为 static 的,比如:Math,Arras,Collections


2. main 方法的探究

在这里插入图片描述

  • public 权限修饰符为什么是 public ???

由于Java虚拟机需要调用类的 main() 方法,所以该方法的访问权限 必须public 才行。

  • 为什么 main 方法的修饰符要是 static 静态的 ???

因为Java虚拟机在执行 main() 方法时,不必创建对象,所以该方法必须是 static ,可以直接调用。

又因为 main 方法是 static 静态的,静态方法无法直接调用非静态的方法/属性,

必须创建对应类的实例对象(new)后,才能通过这个对象去访问该对应类中的非静态方法/属性。

  • main 方法中的形参列表是 string[] args 字符串数组

该形参接收一个 String 类型的数组参数,该字符串数组中保存执行 java 命令时,所传递给所运行类的参数。

在这里插入图片描述


main 也是一个方法,特殊之处就是,它是一个程序入口的方法。不同的类中的是可以相互调用 main 的方法的,如下

因为有两个类,每个类中都有一个 main() 方法,所以执行的时候,你需要选择,想要运行的是哪一个告知编译器。

package blogs.blog2;public class MainTest {public static void main(String[] args) {System.out.println("我是 MainTest 中的 main()方法");}
}class Main2{public static void main(String[] args) {System.out.println("我要调用 MainTest中的main()方法");// 调用 MainTest 中的main()方法MainTest.main(args);}
}

在这里插入图片描述


3. 代码块

在这里插入图片描述

代码块(或初始化块)的作用: 对Java类或者对象进行初始化

代码块的分类:

  • 一个类中代码块中若有修饰符,则只能被 static 修饰,被 static 修饰的代码块被称为 静态代码块
  • 没有任何修饰符,修饰的代码块,被称为非静态代码块

静态代码块的特点:

  • 可以有输出语句
  • 可以对类的属性,类的声明进行初始化操作
  • 不可以对非静态的属性初始化,无法直接调用非静态的的方法/属性,想要 实例化对象 new
  • 静态代码块随着类的加载而加载,并执行,且执行一次。所以静态代码块的执行要先于非静态代码块
  • 一个类中可以有多个静态代码块,若有多个静态的代码块,那么按照从上到下的顺序依次执行。
  • 静态的代码块的诸多限制和 “staitc" 是一样的。

非静态代码块的特点:

  • 和静态代码块一样可以有输出语句
  • 可以对类的数,类的声明进行初始化操作。
  • 不仅可以调用静态的方法/属性,也可以调用非静态的方法 / 属性
  • 一个类中可以有多个非静态代码块,若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
  • 注意的是非静态代码块是,创建对象 (new) 的时候,才会执行,而且每创建一次对象都会执行一次,并且先于构造器执行。

无论是静态代码块/还是非静态代码块,都是加载后并执行的,并不是加载到内存当中不执行的。

在这里插入图片描述


注意: 非静态代码块,不是创建对象 (new) 是不会加载调用执行非静态代码块的

package blogs.blog2;public class BlockTest {public static void main(String[] args) {Person.show();}
}class Person{String name;static String desc;public void eat() {System.out.println("非静态方法");}public static void show(){System.out.println("静态方法");}{System.out.println("非静态代码块");}static{System.out.println("静态代码块");// name = "Tom";  // 静态代码块无法直接调用非静态的// eat();}
}

在这里插入图片描述


静态代码块优先比非静态代码块优先被执行,并且静态代码块仅仅只是执行一次(加载类的那一次)

package blogs.blog2;public class BlockTest {public static void main(String[] args) {Person person = new Person();Person person2 = new Person();}
}class Person{String name;static String desc;public void eat() {System.out.println("非静态方法");}public static void show(){System.out.println("静态方法");}{System.out.println("非静态代码块");}static{System.out.println("静态代码块");// name = "Tom";  // 静态代码块无法直接调用非静态的// eat();}
}

在这里插入图片描述


练习: 观察如下代码的运行结果:

先执行父类,再执行静态代码块

package day15;public class LeafTest {public static void main(String[] args) {new Leaf();System.out.println("*************************");new Leaf();}
}class Root{static {System.out.println("Root的静态初始化块");}{System.out.println("Root的普通初始化块");}public Root(){super();System.out.println("Root的无参数的构造器");}}class Mid extends Root{static{System.out.println("Mid的静态初始化块");}{System.out.println("Mid的普通初始化块");}public Mid() {super();System.out.println("Mid的无参数的构造器");}public Mid(String msg) {// 通过this调用一类中的重载的构造器this();System.out.println("Mid的带参数构造器,其参数数值: "+msg);}
}class Leaf extends Mid{static{System.out.println("Leaf的静态初始化块");}{System.out.println("Leaf的普通初始化块");}public Leaf() {// 通过super调用父类中有一个字符串参数的构造器super("尚硅谷");System.out.println("Leaf的构造器");}
}

在这里插入图片描述


package day15;public class Son extends Father {static {System.out.println("44444444444444444");}{System.out.println("55555555555555");}public Son() {System.out.println("66666666666666");}public static void main(String[] args) {System.out.println("77777777777");System.out.println("**********************************");new Son();System.out.println("*********************************");/*new Son();System.out.println("*************************************");new Father();*/}
}class Father{static{System.out.println("11111111111");}{System.out.println("222222222222");}public Father() {System.out.println("33333333333333");}
}

在这里插入图片描述


3.1 程序中成员变量赋值的执行顺序

如下是对属性赋值的先后所执行的顺序

  1. 默认初始化
  2. 显式初始化
  3. 在代码块中赋值
  4. 构造器中初始化
  5. 有了对象以后,可以通过 ”对象.属性,或对象.方法“ 的方式,进行赋值。
    在这里插入图片描述
public class OrderTest {public static void main(String[] args) {Order order = new Order();System.out.println(order.orderId);}
}class Order{{orderId = 4;}int orderId = 3;public Order() {this.orderId = 5;}}

在这里插入图片描述


把构造器初始化注释掉,结果是

在这里插入图片描述


4. final 关键字

final : 最终的含义。

final 可以用来修饰:类,方法,变量,局部变量(形参)

final 修饰一个,此类就不能被其他类所继承了

比如:System 类,String 类,StringBuffer类:因为里面的方法基本都实现了,没有必要再通过继承扩展了。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


final 修饰方法:表明此方法不可以被重写,比如:Object 类中的 getClass()

在这里插入图片描述


在这里插入图片描述


final 修饰属性:可以考虑赋值的位置有:显示初始化,代码块初始化,构造器,注意是:赋值不是修改,被 final 修饰的变量无法被修改了。

显示初始化

package blogs.blog2;public class FinalTest {final int num = 10;public static void main(String[] args) {FinalTest f = new FinalTest();System.out.println(f.num);}
}

在这里插入图片描述


代码块初始化:

package blogs.blog2;public class FinalTest {final int LEFT;{LEFT = 100;}public static void main(String[] args) {FinalTest f = new FinalTest();System.out.println(f.LEFT);}
}

在这里插入图片描述


构造器初始化:

package blogs.blog2;public class FinalTest {final int num;public FinalTest(int n) {num = n;}public static void main(String[] args) {FinalTest f = new FinalTest(1000);System.out.println(f.num);}
}

在这里插入图片描述


final 修饰局部变量(形参) 表明此形参时一个常量,当我们调用此方法时,给常量形参赋值一实参,一旦赋值以后,就只能在方法体中使用此形参,并且不能再进行重新的赋值操作了。

在这里插入图片描述


package blogs.blog2;public class FinalTest {final int num;public FinalTest(final int n) {num = n;}public static void main(String[] args) {FinalTest f = new FinalTest(1000);System.out.println(f.num);}
}

一般是 static, final 用来修饰属性,全局常量,需要注意的是一般 static 的成员属性,方法也是 static 的

练习:

观察如下代码是否会出现报错,如果不会报错,运行的结果又是什么???

package blogs.blog2;public class FinalTest {public static void main(String[] args) {AA aa = new AA();aa.test(aa);}}class AA {String name;int age ;public void test(final AA aa) {aa.age = 10;   // 这里是否或报错,能否编译成功System.out.println(aa.age);}
}

在这里插入图片描述


解析:

答:不会报错,结果是 10 。

因为 final 修饰的是 AA 这个引用类型的形参,并不会作用于 AA 类中的属性。

如果我修改 AA 这个引用类型的地址,可能就会报错了。


5. 总结:

  1. static 修饰属性,方法,代码块,内部类的不同的作用,
  2. static 静态的随着类一起加载到内存(方法区)当中(仅仅加载一次,所有对象共有),早于 new 对象的加载创建,因为 new 对象,要先加载类,再调用类中的构造方法创建对应的对象。
  3. static 静态的属性,方法,代码块 都无法直接的访问非静态的方法/属性,需要通过 创建实例对象(new)的方式访问
  4. 被 static 修饰的方法,无法被重写,就算编写成了重写的方式了,但是调用的时候,执行的不是子类重写的方法,而是父类中没有被重写的方法。
  5. main 方法的 public , static ,String[] args 的作用。
  6. 代码块:静态代码块,非静态代码块。
  7. 静态代码块:随着类一起加载到内存(方法区)当中,加载的同时,并执行代码块,并且(无论加载多少次类)只执行一次(加载类的那一次)。优先于非静态代码块,优先于构造器。
  8. 非静态代码块:只有当创建实例对象(new)的时候才会被加载并执行,创建多少次对象就会执行多少次非静态代码块。
  9. final 最终的,可以修饰:属性(不可修改),形参(不可修改),方法(无法重写),类(无法继承)。

6. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!!!


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_239417.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作手册(GB8567——88)基于协同的在线表格forture-sheet

操作手册(GB8567——88) 1引言 1.1编写目的 为了帮助用户更好的上手本系统,加快用户对forture-sheet在线表格的快速入门,本操作手册详细介绍使用forture-sheet的部分基础操作以及注意细节。 1.2前景 待开发系统的名称&#x…

ASP.NET开发的医疗健康咨询平台源码 养生知识咨询 寻根问药平台源码 C#源码

一、源码特点: 爱心医生健康知识门户网站是一个权威的医疗科普视频、语音、知识、医疗健康问答平台。 包含所有源代码和数据库,可以直接部署到IIS中使用。 二、菜单功能 网站页面: 1、首页:包含幻灯片。 2…

InnoDB详解2

文章目录InnoDB详解21 行格式1 Compact行格式详解1 变长字段长度列表(两个字节)2 NULL值列表(1个字节)3 记录头信息 (重点)2 Dynamic行格式2 页的上层结构InnoDB详解2 1 行格式 规定每条记录是怎么存储的…

解决资源消耗,top的运用记录

第一条命令uptime load average 后面的三个数字,分别代表1分钟、5分钟和15分钟内机器的平均负载 使用top命令解决负载问题 Cpu(s)这一行提供了CPU运行情况信息 这些缩写分别代表了不同含义 (1)us:用户CPU时间 运行非优雅的用户进程所占CPU时间的百…

Python学习笔记(十九)——Matplotlib入门上

目录 Matplotlib简介 导入matplotlib模块 图的参数说明 matplotlib图像组成部分介绍 matplotlib绘图步骤分析 matplotlib实现简单图像 matplotlib画布 画布-plt.figure() 实例 同一画布制作多张图像 创建多个子图 实例 plt.subplots 相关参数 调整subplot周围的间距…

简单记录一下怎么看package.json文件

首先每个vue工程文件从仓库克隆代码下来的时候,一般都会包含这个文件,这个文件非常重要,package.json包含了关于项目重要信息,如下图所示 其中包含了name、version、description、author、scripts、dependencies、devDependencies…

小结 | 决策树

一.基本原理 决策树是一种树状结构模型,每一个根节点都是一个特征判断,它的叶子节点就是它的特征分类结果 决策树是一种分类和回归的基本模型,是一棵树的形式,其实就是将平时所说的 if-else 语句构建成了树的形式。决策树主要包…

短视频引流+私域流量沉淀,一个全新的短视频和链动模式结合方案

在微盟企微助手微盟智慧零售团队的协助下,今年7月底么么茶正式开始运营企微私域,截至当前,在短短3个月时间已成功沉淀7万私域客户,线上商城GMV超145万。 么么茶旅拍的核心流量来源自公域短视频平台,品牌基于服务覆盖下…

deck.gl 调研

0 结论 deck gl 是基于 WebGL 的数据可视化框架,可以集成在主流的地图框架(arcgis,google maps,mapbox )中使用, 也可以单独使用。 deck gl 通过layer进行数据可视化,支持多种展示效果&#xf…

ASP.NET开源版MES加工装配模拟系统源码/WinForm工厂加工装配系统源码/流程工序管理

一、源码描述 本系统用户大学机械科上位机加工装配模拟实验,目前正常用于实验当中。环境:VS2010(C# .NET4.0,多层结构)、sqlserver2008 r2 ;Winform;使用到RFID读写器(设备是可以变更的,修改RFID.Library项目的…

数字三角形问题

数字三角形问题一、题目描述二、题目分析1、问题分析2、思路分析(1)状态转移方程状态表示状态转移(2)循环的设计三、代码实现一、题目描述 二、题目分析 1、问题分析 这道题给我们的第一眼感觉就是情况太多了,太复杂…

【TypeScript】常用类型声明详情概述

目录 TypeScript常用类型 类型注解 TS类型概述 原始类型 数组类型 对象类型 函数类型 类型别名 接口 元组 字面量类型 枚举 any类型 typeof操作符 类型推论 类型断言 TypeScript常用类型 TypeScript是JS的超集,TS提供了JS的所有功能,并额…

PyInstaller的常用打包命令

学习了pyqt后,设计了界面,并且需要打包为exe程序。 每次打包时,都要查好久资料,故此记录一下常用的命令。 PyInstaller 是一个 Python 应用程序打包工具,它可以将 Python 程序打包为单个独立可执行文件。 要使用 P…

11Python面相对象基础语法

面相对象基础语法 01. dir 内置函数 在 Python 中 对象几乎是无所不在的,我们之前学习的 变量、数据、函数 都是对象 在 Python 中可以使用以下两个方法验证: 使用内置函数 dir 传入 标识符 / 数据,可以查看对象内的 所有属性及方法 提示…

虚拟机docker网络问题处理

问题 我们有2台设备,ip 为 172.20.30.1 172.20.30.2 ,虚拟机上的服务需要连接这2台设备,网络已经做通了,可以正常连接虚拟机异常关闭,重新开启后。发现服务有些问题,就打算将docker服务重新部署&#xff0…

面渣逆袭:Java并发六十问,快来看看你会多少道

这篇文章有点长,四万字,图文详解六十道Java并发面试题。人已经肝麻了,大家可以点赞、收藏慢慢看!扶我起来,我还能肝! 基础 1.并行跟并发有什么区别? 从操作系统的角度来看,线程是…

善康医药冲刺科创板上市:计划募资13亿元,上半年亏损5000万元

近日,深圳善康医药科技股份有限公司(下称“善康医药”)在上海证券交易所递交招股书,准备在科创板上市。本次冲刺上市,善康医药计划募资13.27亿元,将用于新药研发项目、创新药高端制剂生产基地建设项目、营销…

Influxdb双写服务influxdb-relay部署配置【离线】

Background Influxdb社区版未提供集群方案,官方提供的集群模式为闭源收费版本,具体收费明细不太清楚哈,有知道的请留言告知哈。官方开源的influxdb-relay仅仅支持双写功能,并未支持负载均衡能力,仅仅解决了数据备份的问…

Simulink代码生成: Switch模块及其代码

本文描述Switch模块的建模并研究生成的代码。 文章目录1 Simulink中的Switch模块2 Switch模块建模及代码生成3 Switch模块其他用法3.1 多重Switch3.2 通过标定量Switch4 总结1 Simulink中的Switch模块 在Simulink中Switch模块时非常常见的,通常用于根据一定地条件选…

【代码随想录】二刷-贪心算法

贪心算法 《代码随想录》 什么是贪心? 贪心的本质是选择每一阶段的局部最优,从而达到全局最优。 贪心没有规定的套路。 刷题或面试的时候,手动模拟一下感觉可以局部最优退出整体最优,而且想不到反例,那么就试一试贪心。…