Java中static、final关键字【详解】

news2024/12/28 4:05:40

文章目录

  • 一、static关键字
    • 1.1 成员变量
      • 1.1.1 静态变量及其访问
      • 1.1.2 实例变量及其访问
    • 1.2 成员方法
      • 1.2.1 静态方法及其访问
      • 1.2.2 实例方法及其访问
    • 1.3 小结
    • 1.4 static应用知识
  • 二、final关键字
    • 2.1 修饰类:不能被继承
    • 2.2 修饰方法
    • 2.3 修饰变量-局部变量
      • 2.3.1 局部变量——基本类型
      • 2.3.2 局部变量——引用类型
    • 2.4 修饰变量-成员变量

一、static关键字

  • static是静态的意思,可用来修饰 成员方法、成员变量。static修饰后的变量、方法,可以被类的所有对象共享
  • static修饰成员变量之后,这个变量被称为类变量静态成员变量;无static修饰的成员变量是属于每个对象的,这个变量被称为实例变量
  • static修饰方法之后,这个方法被称为类方法静态方法;无static修饰的成员方法是属于每个对象的,这个成员方法也叫做实例方法

1.1 成员变量

成员变量分类

  • 静态成员变量:有static修饰,属于类、加载一次、内存中只有一份。表示公司名称、在线人数等需要被类的所有对象共享的信息
  • 实例成员变量:无static修饰,属于每个对象。譬如user类的name、age

1.1.1 静态变量及其访问

静态成员变量(被static修饰,属于类、加载一次、内存中只有一份)。直接用 类名 访问即可,因为类只有一个,所以静态成员变量在内存区域中也只有一份,所有的对象都可以共享该变量。

  • 定义格式
修饰符 static 数据类型 变量名 = 初始值;
  • 访问
类名.静态成员变量(推荐)
对象.静态成员变量(不推荐)
  • 举例:现在需要定义abc公司全部的员工,这些员工类的对象的公司属性应该都是“abc”,这个时候就可以将公司属性定义为static修饰的静态成员变量
public class Employee {
    //静态成员变量,属于类,只有一份
    public static String companyName = "abc";   
    
    //实例变量
    private String name;
    private Integer age;
    
    //...
}


//访问
public static void main(String[] args) {
    System.out.println(Employee.companyName);  //abc
    Employee.companyName = "learn";
    System.out.println(Employee.companyName);  //learn
    
    Employee employee1 = new Employee("zhangsan", 18);
    System.out.println(employee1.getAge()); //18
}

1.1.2 实例变量及其访问

无static修饰的成员变量

注意:实例成员变量属于每个对象,必须创建类的对象才能访问

访问:对象.实例成员变量

1.2 成员方法

成员方法分类

  • 静态成员方法:有static修饰,属于类、内存中只有一份。
  • 实例成员方法:无static修饰,属于每个对象,只能用对象访问。

表明对象自己的行为的、且方法中需要访问实例成员的,该方法必须声明为实例方法。

如果该方法是以执行一个共有功能为目的,可以声明为静态方法。

1.2.1 静态方法及其访问

静态方法(被static修饰,属于类、内存中只有一份)。直接用 类名访问即可。因为类只有一个,所以静态方法在内存区域中也只存在一份。所有的对象都可以共享这个方法。

  • 定义格式
修饰符 static 返回类型 方法名(param) {}
  • 访问
类名.静态方法(推荐)
对象.静态方法(不推荐)
  • 举例
public class Employee {
    public static String companyName = "abc";
    private String name;
    //...
    
    public static void work() {
        System.out.println("我们都在" + companyName + "公司工作");
    }

    public void achive() {
        System.out.println(name + "实现大成就");
    }
    
}


public static void main(String[] args) {
    Employee employee1 = new Employee("zhangsan", 18);

    Employee.work();
    //Employee.achive();   //报错,必须使用对象范围
    employee1.achive();
}

1.2.2 实例方法及其访问

无static修饰的成员方法

注意:实例方法是属于每个对象,必须创建类的对象才可以访问

访问:对象.实例方法

1.3 小结

  • 1)当static修饰成员变量或者成员方法时,该变量称为静态变量,该方法称为静态方法。该类的每个对象都共享同一个类的静态变量和静态方法。任何对象都可以更改该静态变量的值或者访问静态方法。但是不推荐这种方式去访问。因为静态变量或者静态方法直接通过类名访问即可,完全没有必要用对象去访问。

  • 2)无static修饰的成员变量或者成员方法,称为实例变量、实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。

  • 3)static访问注意事项

    • 静态方法只能访问静态成员。不能直接访问实例成员

    • 实例方法可以访问静态成员,也可以访问实例成员

    • 静态方法中是不可以出现this关键字的。this指当前对象,静态方法中不用声明实例对象

在java中,程序执行时 类的字节码文件会被加载到内存中,如果类没有创建对象 类的成员变量则不会分配到内存;但对于被static修饰的静态变量/方法,堆中有一个专属的静态变量区,当JVM虚拟机将字节码加载到内存时,会为静态变量/方法在堆中分配出一段空间用于放置值,即静态变量/方法跟随类加载而加载

当你通过类定义对象的时候,才会在堆内存中为不同的对象分配空间。

(由于静态方法已经存在内存中,而非静态方法不存在,使用一个存在的方法去调用一个不存在的方法,不可行,故静态方法无法访问实例成员)

若想要使用静态方法调用非静态方法,只需要实例化new一个类对象,此时jvm虚拟机就会为对象开辟一块内存,该类的所有方法也随之被存储到内存当中。此时静态方法和非静态方法都在内存当中,所以在静态方法中可以使用对象去调用一个非静态方法。

  • 4)static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以可被所有对象共享。

  • 5)无static修饰的成员,是属于对象,对象有多少个,他们就会出现多少份。所以必须由对象调用。

  • 6)内存原理

在这里插入图片描述

在这里插入图片描述

1.4 static应用知识

  • 工具类

1)概述:类中都是一些静态方法,每个方法都是以完成一个共用的功能为目的,这个类用来给系统开发人员共同使用。

2)由于工具里面都是静态方法,直接用类名即可访问,因此,工具类无需创建对象,建议将工具类的构造器进行私有。

  • 静态代码块

1)代码块概述:代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。在Java类下,使用 { } 括起来的代码被称为代码块 。

2)静态代码块:static{}。特点——需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次。使用场景——在类加载的时候做一些静态数据初始化的操作,以便后续使用

  • 单例设计模式

1)单例模式:可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象。例如任务管理器对象我们只需要一个就可以解决问题,节省内存空间

2)饿汉单例模式:在用类获取对象的时候,对象已经提前为你创建好了

设计步骤:

(1)定义一个类,把构造器私有

(2)定义一个静态变量存储一个对象

public class SingleInstance {
    public static SingleInstance instance=new SingleInstance();
 
    private SingleInstance() {
        System.out.println("创建了一个对象");
    }
}

3)懒汉单例模式:在真正需要该对象的时候,才去创建一个对象(延迟加载对象)

设计步骤:

(1)定义一个类,把构造器私有

(2)定义一个静态变量存储一个对象

(3)提供一个返回单例对象的方法

public class SingleInstance {
    private static SingleInstance instance;
 
    public static SingleInstance getInstance(){
        if (instance==null){
            instance=new SingleInstance();
        }
        return instance;
    }
}

参考https://blog.csdn.net/Javascript_tsj/article/details/127163683

二、final关键字

当我们提供了一个父类,子类可以通过方法重写 在父类的基础上改写父类内容。如果有个方法 不希望别人修改,怎么解决呢?

Java提供了final关键字,表示修饰的内容不可变。

final:最终的、不可改变的。可用于修饰类、方法、变量。

  • 类:被修饰的类,不能被继承
  • 方法:被修饰的方法,不能被重写
  • 变量:被修饰的变量,有且只能被赋值一次

2.1 修饰类:不能被继承

final修饰的类 不能被继承,即当前这个类不能有任何的子类。格式如下

final class 类名 {
}

注意:一个类如果被final修饰,那么其中所有的成员方法都无法进行覆盖重写,因为无子类。

查看API发现,像 public final class Stringpublic final class Mathpublic final class Scanner 等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。

final class Fun1 {
}
// class A extends Fun1 {} // 报错,不能继承final的类

2.2 修饰方法

final修饰的方法,不能被重写。格式如下:

修饰符 final 返回值类型 方法名(参数列表){
    //方法体
}

注意:对于类、方法来说,abstract关键字和final关键字不能同时使用。有抽象方法的abstract类被继承时,其中的方法必须被子类Override,而final不能被Override,互相矛盾。

public class Fun2 {
    final public void show1() {
        System.out.println("Fun2 show1");
    }
    public void show2() {
        System.out.println("Fun2 show2");
    }
}


public class SonFun2 extends Fun2{
    //重写final方法 会报错
//    @Override
//    final public void show1() {
//        System.out.println("Fun2 show1");
//    }
    
    @Override
    public void show2() {
        System.out.println("Fuu2 show2");
    }
}

2.3 修饰变量-局部变量

2.3.1 局部变量——基本类型

基本类型的局部类型,被final修饰后,只能赋值一次,不能再修改,“一次赋值,终身不变”。代码如下

public class FinalVariable {
    public static void main(String[] args) {
        // 声明变量,使用final修饰
        final int a;
        // 第一次赋值
        a = 18;
        // 第二次赋值
        a = 24; // 报错,不可重新赋值

        // 声明变量,直接赋值,使用final修饰
        final int b = 18;
        // 第二次赋值
        b = 24; // 报错,不可重新赋值
    }
}

2.3.2 局部变量——引用类型

引用类型被final修饰后,地址值不能改变,否则报错。

虽然地址值不能变,但内容可以变(地址所指向的对象可以变)

public class Person {
    private String name;

    public Person() {
    }
    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

1)引用类型 无final修饰,地址不同

public static void main(String[] args) {
    Person p1 = new Person("zhangsan");
    System.out.println(p1);             //打印地址  xx.Person@5c8da962
    System.out.println(p1.getName());   //zhangsan

    p1 = new Person("lisi");
    System.out.println(p1);             //打印地址  xx.Person@512ddf17
    System.out.println(p1.getName());   //lisi
}

在这里插入图片描述

2)被final修饰,地址值不可改变,否则报红。但是可以修改对象内容

final Person p2 = new Person("Jenny");
//错误写法。final修饰引用类型变量,其中的地址不可改变
//p2 = new Person("Jack");

System.out.println(p2.getName());  //Jenny
p2.setName("Jack");                //修改对象内容
System.out.println(p2.getName());  //Jack

2.4 修饰变量-成员变量

成员变量如果被final修饰,一旦有了初始值 就不能被重新赋值。

由于成员变量具有默认值,用final关键字修饰后 不会再给默认值,必须手动赋值,否则会报错。因此必须手动初始化,有两种初始化方式——显示初始化和构造方法初始化。

在这里插入图片描述

对于final类型的成员变量,有两种初始化方式(赋值方式),显示初始化和构造方法初始化,只能选其中一个,且不需要setXX函数。

  • 显示初始化:在定义成员变量的时候里面赋值(常用)
public class Person {
    private final String name = "Jenny";
}

在这里插入图片描述

  • 构造方法初始化:必须保证所有重载的构造方法,都会对final修饰的成员变量进行赋值,即每个构造方法中都要赋值一次(不常用、了解即可)
public class Person {
    //对于final类型的成员变量,有两种初始化方式(赋值方式),显示初始化和构造方法初始化,只能选其中一个

    // 定义成员变量时指定默认值,合法。
    final String name = "Jenny";
    final int num;

    public Person() {
        // 在构造器中分配初始值
        num = 20;
    }

    public Person(int num) {
        // 在构造器中分配初始值
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }
}

被final修饰的常量名称,一般都有书写规范,所有字母都大写

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

背景减除(1)--bgslibrary Windows编译和使用

入侵监控领域中,在固定场景下,需要检测和监控的入侵物体种类繁多,无法具体穷尽。传统的CV算法提取的特征应用场景有限,无法完成大量物体的监控;深度学习目标检测方法没法收集到无穷无尽的物体种类,因此监督…

水牛社五大赚钱栏目概览:轻松了解项目核心与赚钱原理

很多新用户首次访问水牛社官网时,可能会感到有些迷茫。由于软件介绍相对较长,部分朋友可能缺乏耐心细读。然而,若您真心希望在网络上找到赚钱的机会,深入了解我们的发展历程将大有裨益。简而言之,本文旨在快速带您领略…

大数据基础:Linux基础详解

课程介绍 本课程主要通过对linux基础课程的详细讲解,让大家熟练虚拟机的安装使用,Linux系统的安装配置,学习掌握linux系统常用命令的使用,常用的软件安装方法,制作快照,克隆,完成免密登录&…

深度学习图像处理02:Tensor数据类型

上一讲深度学习图像处理01:图像的本质,我们了解到图像处理的本质是对矩阵的操作。这一讲,我们讲介绍深度学习图像处理的基本数据类型:Tensor类型。 在深度学习领域,Tensor是一种核心的数据结构,用于表示和…

蓝桥杯单片机快速开发笔记——特训2 按键的长按与短按

一、题目要求 在CT107D单片机综合训练平台上,通过I/O模式编写代码,实现以下功能: 系统上电后,关闭蜂鸣器、继电器和全部指示灯,数码管显示初始值为28,仅显示数码管最右边两位。利用定时器0实现10ms间隔定…

代码随想录第20天| 654.最大二叉树 617.合并二叉树

654.最大二叉树 654. 最大二叉树 - 力扣(LeetCode) 代码随想录 (programmercarl.com) 又是构造二叉树,又有很多坑!| LeetCode:654.最大二叉树_哔哩哔哩_bilibili 给定一个不重复的整数数组 nums 。 最大二叉树 可以…

基于java+springboot+vue实现的医院门诊信息管理系统(文末源码+Lw+ppt)23-325

摘 要 系统根据现有的管理模块进行开发和扩展,采用面向对象的开发的思想和结构化的开发方法对医院门诊信息的现状进行系统调查。采用结构化的分析设计,该方法要求结合一定的图表,在模块化的基础上进行系统的开发工作。在设计中采用“自下而…

不敢想象吧!Anzo Capital发现不仅经济事件影响汇率天气也是

在投资交易中弄懂汇率的走势方向,对各位投资者的交易盈利那还不是小菜一碟,但各位投资者你们想象不到吧!Anzo Capital发现不仅经济事件能影响汇率,就连天气也能轻易影响汇率。 就用2015年1月15日的经济事件来说,当瑞…

pandas读写excel,csv

1.读excel 1.to_dict() 函数基本语法 DataFrame.to_dict (self, orientdict , into ) --- 官方文档 函数种只需要填写一个参数:orient 即可 ,但对于写入orient的不同,字典的构造方式也不同,官网一共给出了6种&#xff0c…

基于springboot+vue的流浪动物管理系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

2002-2023年各地级市环境规制强度数据(环保词频统计)

2002-2023年各地级市环境规制强度数据(环保词频统计) 1、时间:2002-2023年 2、来源:政府工作报告 3、指标: 行政区划代码、年份、城市、所属省份、文本总长度、仅中英文-文本总长度、文本总词频-全模式、文本总词频…

快速熟悉ElasticSearch的基本概念

1.全文检索 全文检索是通过文本内容进行全面搜索的技术。通过全文检索可以快速地在大量文本数据中查找包含特定关键词或者短语的文档,并且返回相关的搜索结果。 检索和查询的区别 检索没有搜索条件边界,检索的结果取决于相关性,相关性计算…

ssm004新生报到系统+jsp

新生报到系统的设计与实现 摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对新生报到信息管理混乱,出错率…

JS运行时大盘点,出新JS运行时了!

大家好,我是奇兵, 在前端技术日新月异的今天,新的 JavaScript 运行时环境不断涌现,它们为开发者提供了更多的选择和可能性。近期,诸如 LLRT 和 WinterJS 等新运行时环境的发布,进一步丰富了 JavaScript 运…

实战 | 任意密码重置+CRRF

一、XSS漏洞 在商城的搜索处,输入标准语句的传参直接就可以弹窗 二、逻辑漏洞-用户枚举 在用户注册界面,点击发送验证码,然后用BURP发包 更改手机号传参,这里手机号传参没有进行加密,直接用手机号的位置进行爆破 正确的…

cad怎么画洗菜盆平面图?

CAD绘制住宅平面布置图的时候,特别是对厨房区域的绘制时,需要使用到洗菜盆图块该怎么绘制洗菜盆平面图呢?下面我们就来看看详细的教程。 1、打开AutoCAD 2013软件,点击【图层特性管理器】,点击【新建图层】&#xff0…

maya打开bvh脚本

目录 maya打开脚本编辑器 运行打开bvh脚本 maya导出bvh脚本 maya打开脚本编辑器 打开Maya软件,点击右下角 “脚本编辑器” 运行打开bvh脚本 https://github.com/jhoolmans/mayaImporterBVH/blob/master/bvh_importer.py import os import re from typing impo…

Redis消息队列与thinkphp/queue操作

业务场景 场景一 用户完成注册后需要发送欢迎注册的问候邮件、同时后台要发送实时消息给用户对应的业务员有新的客户注册、最后将用户的注册数据通过接口推送到一个营销用的第三方平台。 遇到两个问题: 由于代码是串行方式,流程大致为:开…

关于网格数据导出指定格式的测试(以Gmsh导出nas格式为例)

本文主要讲述Gmsh如何导出nas格式的网格数据,众所周知,Gmsh可以导出多种网格数据格式,比如大家熟悉的msh、stl、inp、cgns(似乎不完善)等等,但是gmsh不支持nas格式的导出,只支持nas格式的导入&a…

基于java+springboot+vue实现的图书借阅系统(文末源码+Lw+ppt)23-328

摘 要 伴随着我国社会的发展,人民生活质量日益提高。于是对系统进行规范而严格是十分有必要的,所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套“期待相遇”图书借阅系统,帮助商…