《走进对象村2》特殊的- static

news2024/11/22 11:08:39

文章目录

  • 🚀文章导读
  • 1.1static修饰成员变量
  • 1.2static修饰成员方法
  • 1.3代码块
    • 1.3.1代码块概念及分类以及不同代码块之间的运行顺序
    • 1、普通代码块
    • 2、构造代码块
    • 3、静态代码块
  • static存在的意义
  • 面试题:
    • 1、static的独特之处
    • 2、 静态变量和实例变量的区别
    • 3、静态方法和实例方法有何不同

🚀文章导读

本篇文章主要讲解了static的作用,和一些代码块的分类,以及它们之间的先后执行顺序

看完本篇文章,需要理解一下几点:

1、static修饰的变量和方法在内存中是如何分配的

2、static修饰的方法如何调用

3、static存在的意义

4、static的独特之处

1.1static修饰成员变量

在java中被static修饰的成员,称为静态成员,也可以称为类成员,不属于某个具体的对象,是所有对象所共享的

什么意思呢?下面通过代码来进行讲解

假如,这里有三个同班的学生,它们分别有自己的名字和年龄,所以在每次实例化一个对象时,都会对每个学生的属性进行一份保存,例如:

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        Student student1 = new Student("A", 15);
        Student student2 = new Student("B", 17);
        Student student3 = new Student("C", 20);

    }

分别创建了三个学生对象,通过运行可以看出,每个对象中也都保存了一份学生属性

在这里插入图片描述
假如设,在类当中设置一个班级属性,因为这三个学生都是一个班的,所以班级肯定也是相同的,假如设置一个classroom,可以看到,三个学生的classroom都是一样的,但是仍然在内存中也保存了三份,这样就有点浪费了,我们只需要保存一份就行了,所以这里就用到了static。

在这里插入图片描述

下面用static对classroom进行修饰,static修饰的成员变量也称为静态成员变量

public class Student {
    private String name;
    private int age;
    private static String classroom;

    public Student(String name, int age,String classroom) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        Student student1 = new Student("A", 15,"111");
        Student student2 = new Student("B", 17,"111");
        Student student3 = new Student("C", 20,"111");
        Student.classroom = "111";//通过类名访问classroom
        //student1.classroom = "111";通过对象的引用访问classroom
    }

在这里插入图片描述

通过以上代码可以看到两个问题:

1、在创建对象时,对象中只有name和age并没有classroom,那classroom保存到了哪里呢?

2、在对static修饰的成员变量进行访问时,有两种方式,具体哪一种比较好呢?

解答1:当实例化一个对象时,对象中会保存类的成员变量,而对象会保存在栈区,但是当用static修饰时,成员变量就会保存在方法区,所以,static修饰的成员变量是不属于某个具体对象的,是所有对象所共享的。

解答2:对static修饰的变量(静态变量)进行访问时,通过:类名==.成员变量 进行访问,也可以通过先实例化一个对象,通过对象的引用进项访问,但是不建议采用后者这种方式,因为,后者是通过对象的引用去访问的,而静态成员是存储在方法区的,是不依靠对象的,所以建议采用类名.==成员变量进行访问。而非静态成员变量的访问是通过对象的引用进行访问的。

静态成员变量的特性

1、不属于某个具体对象,是类的属性,存放在方法区中,是所有对象所共享的,不存储在某个对象的空间中

2、既可以通过对象访问,也可以通过类名访问,但是建议用类名访问

3、生命周期伴随类的一生(随类的加载而创建,随类的销毁而销毁)

1.2static修饰成员方法

一般大多数类中的成员变量都用private修饰,因为这样就对类中的成员进行了很好的隐秘性,是一种封装的体现,而成员方法一般设置成public,那么问题是,被static修饰的成员成员方法要如何进行访问呢?

public class Student {
    private String name;
    private int age;
    public static String classroom;
    public void func1() {
        System.out.println("这是一个非静态成员方法");
    }
    public static void func2() {
        System.out.println("这是一个静态成员方法");
        System.out.println("这是一个静态方法"+this.name);//这个是错误的,不能使用this
    }
    public static int add(int a, int b) {//static修饰的成员方法
        return a+b;
    }
    public static void main(String[] args) {//静态成员方法
        System.out.println(add(5, 3));//直接调用静态成员方法
        Student.func2();
        Student stu = new Student();//实例化一个对象
        stu.func1();//通过对象的引用对非静态方法进行访问
        func1();//这个是错误的,不能直接调用非静态方法
        
    }

对静态成员方法的访问也是通过类名==.==方法名 进行访问的,在静态方法中去调用静态方法时,如果被调用的静态方法有返值,那么是可以直接调用的,如果没有返回值的话需要通过类名==.==方法名进行调用,但是,是不可以直接对非静态方法进行调用的,需要先实例化一个对象,通过对象的引用访问非静态方法。注意,在静态方法中,也不可以使用this,因为静态方法是不依赖对象的。所以:

总结

在静态方法中,可以直接调用静态方法,但不能直接调用非静态方法,对于非静态方法的调用,需要先实例化一个对象,通过对象的引用调用非静态方法

在非静态方法中,可以直接调用静态方法,也可以直接调用非静态方法、

静态方法特性

1、不属于某个具体对象,是类方法

2、可以通过对象调用,也可以通过类名==.==静态方法名()的方式调用,更推荐后者

3、不能在静态方法中直接访问任何非静态成员变量

1.3代码块

1.3.1代码块概念及分类以及不同代码块之间的运行顺序

**使用这种 {} 定义的代码称为代码块。**代码块又分为四种:

1、普通代码块

2、构造块

3、静态块

4、同步代码块

1、普通代码块

public class Student {

    public static void main(String[] args) {
        {
            int x = 30;
            System.out.println(x);
        }
        System.out.println(x);//这样写是错误的
    }

普通代码块是定义在方法中的代码块,因为 int x 是定义在代码块内部的局部变量,所以x的生命周期是在代码块内部,出了代码块x就自动销毁了。

2、构造代码块

构造块:定义在类中的代码块。也称为实例代码块,用于初始化实例成员变量

public class Student {

    private String name;
    private int age;
    private String sex;
	//构造方法
    public Student() {
        System.out.println("这是一个构造方法");
    }
    //构造代码块
    {
        this.name = "lisi";
        this.sex = "男";
        this.age = 15;
        System.out.println("这是一个构造块");
    }
    //成员方法
    public void show() {
        System.out.println("name:"+name+" "+"age"+age+" "+"sex"+sex);
    }

    public static void main(String[] args) {
        Student stu = new Student();
        stu.show();
    }

在这里插入图片描述

通过运行结构可以看到,代码执行时,首先编译了构造代码块,然后执行了构造方法,最后执行了普通的成员方法,所以排一下顺序是:构造代码块->构造方法->成员方法

3、静态代码块

使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量

public class Student {

    private String name;
    private int age;
    private String sex;
    private static int weight;

    //构造代码块
    {
        this.name = "lisi";
        this.age = 14;
        this.sex = "女";
        System.out.println("这是一个构造代码块");
    }
    //静态代码块
    static {
        weight = 54;
        System.out.println("这是第一个静态代码块");
    }
    static  {
        System.out.println("这是第二个静态代码块");
    }
    //构造方法
    public Student() {
        System.out.println("这是一个构造方法");
    }
    public void show() {
        System.out.println("这是一个成员方法");
        System.out.println("name:"+name+" "+"age:"+age+" "+"sex:"+sex+" "+"weight:"+weight);
    }
    public static void main(String[] args) {
        Student stu = new Student();
        stu.show();
    }

第一种情况:

在这里插入图片描述

由上述代码可以看出,当出现静态代码块时,执行的顺序首先是静态代码库,当有多个静态代码时,按照定义的顺序执行,其次是构造代码块,然后是构造方法,最后是成员方法。

第二种情况:

在这里插入图片描述

在这里插入图片描述

当在main方法中创建两次对象时,处了静态代码块外,其他代码块都执行了第二次,所以可以得出结论,对于静态成员变量,JVM只会在类首次加载时分配一次内存,而不管生成多少个对象,静态代码块都只执行一次。

第三种情况:

public class Student {

    private String name;
    private int age;
    private String sex;
    private static int weight;

    //构造代码块
    {
        this.name = "lisi";
        this.age = 14;
        this.sex = "女";
        System.out.println("这是一个构造代码块");
    }
    //静态代码块
    static {
        weight = 54;
        System.out.println("这是第一个静态代码块");
    }
    static  {
        System.out.println("这是第二个静态代码块");
    }
    //构造方法
    public Student() {
        System.out.println("这是一个构造方法");
    }
    public void show() {
        System.out.println("这是一个成员方法");
        System.out.println("name:"+name+" "+"age:"+age+" "+"sex:"+sex+" "+"weight:"+weight);
    }
    public static void main(String[] args) {
        //Student stu = new Student();
        //stu.show();
        //System.out.println("===================");
        //Student stu1 = new Student();
        //stu.show();
    }

在这里插入图片描述

由上述代码可知,在不创建对象时,只执行了静态代码块,足以证明:静态代码块是在类初次加载时才会被执行,而构造代码块是依赖于对象的,只有创建了对象,构造代码块、构造方法、成员方法才会被执行。

注意事项:

1、实例代码块只有在创建对象时才执行

2、不管生成多少个对象,静态代码块都只执行一次

3、静态成员变量是类的属性,JVM只会在类首次加载时分配一次空间并初始化

4、如果一个类中包含多个静态代码块,在编译时,编译器会按照定义的先后顺序依次执行

static存在的意义

1、static主要的意义是用于创建独立的不依赖于对象的变量和方法。以至于没有创建对象,也能使用属性和调用方法

2、static关键字还有一个比较关键的作用是用来形成静态代码块已优化程序性能,类中可以有多个静态代码块,在类初次加载的时候,会按照static块的顺序执行每个static代码块,并且只会执行一次,只分配一次内存空间,而且是最先运行的

3、为什么说static块可以用来优化程序性能?因为它的特性:只会在类加载的时候执行一次,因次,很多时候会将一些只需要进行一次的初始化操作都放在静态代码快中

面试题:

1、static的独特之处

1、被static修饰的成员变量或方法是独立与该类的任何对象,也就是说这些变量和方法不属于任何一个实例对象,而是被所有对象所共享的

2、在类被加载时,就会去加载被static修饰的部分,而且在类第一次使用时加载并初始化,注意,第一次用就会被初始化,以后根据需要还可以在进行赋值

3、static变量值在类初次加载的时候分配空间,以后创建类对象的时候不会再重新分配。赋值的话是可以任意赋值的

4、被static修饰的变量或者方法是优先与对象存在的,也就是说当一个类加载完毕以后,几遍没有创建对象,也可以去访问

5、常见的static应用场景:1、修饰成员变量,2、修饰成员方法,3、静态代码块,4、修饰类【只能修饰内部类也就是静态内部类】

2、 静态变量和实例变量的区别

静态变量:静态变量不属于任何实例对象,是属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只会为静态变量分配一次内存空间;

实例变量:每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量

3、静态方法和实例方法有何不同

1、调用方式不同:

在外部调用静态方法时,可以使用“类名.方法名“的方式,也可以使用”对象名.方法名“的方式、而实例方法只能使用后者,也就是说,调用静态方法无需实例化对象

2、访问位置有区别

在静态方法中,可以直接访问静态成员,而不能直接访问非静态成员,在实例方法内部则没有此限制

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

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

相关文章

前端——HTML

1.html的标准结构 【1】先建立一个普通文本文档&#xff0c;将文本的后缀改为.html 【2】编辑&#xff1a;标准结构 <html> <head></head> <body> this is my first </body> </html> 最外层是标签<html>然后<head>标…

如何用 AI 练英语口语?

语言学习&#xff0c;就得靠多训练。 痛点 有的小伙伴学了很长时间的英语&#xff0c;但学到的却是「哑巴英语」&#xff0c;特点是见着外国人张不开嘴。这里面有多种因素&#xff0c;但最主要还是练得太少。语言这东西就得靠多训练。经常和外国人说话&#xff0c;语言能力很快…

HTML常用标签总结

文章目录 HTML结构HTML常见标签注释标题标签h1 - h6段落标签p换行标签br格式化标签图片标签img超链接标签a表格标签table列表标签ul ol dl表单标签select标签textarea标签无语义标签div和span HTML结构 形如&#xff1a; <body></body>这样的标签就是一个HTML标签…

15.Java基础

1.xml 1.1概述【理解】 万维网联盟(W3C) 万维网联盟(W3C)创建于1994年&#xff0c;又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者&#xff1a; Tim Berners-Lee (蒂姆伯纳斯李)。 是Web技术领域最具权威和影响力的国际中立性技术标准机构。 到目前为…

linux部署k8s

linux部署k8s 0、k8s的前世今生1、下载k8s2、k8s文档2.1、容器化部署的优越性2.1.1、Traditional deployment era2.1.2、Virtualized deployment era2.1.3、Container deployment era 3、安装k8s3.1、Install kubectl on Linux3.2、 0、k8s的前世今生 参考链接: https://kuber…

《基于智能手机采集的PPG信号预测血管老化》阅读笔记

目录 一、论文摘要 二、论文十问 Q1: Q1论文试图解决什么问题&#xff1f; Q2: 这是否是一个新的问题&#xff1f; Q3: 这篇文章要验证一个什么科学假设&#xff1f; Q4: 有哪些相关研究&#xff1f;如何归类&#xff1f;谁是这一课题在领域内值得关注的研究员&#xff1f…

OpenCV的highgui模块

Opencv把用于操作系统、文件系统以及摄像机等硬件设备交互的函数纳入到highgui&#xff08;High-level Graphical User Interface)模块中&#xff0c;我们可以利用该模块方便地打开窗口、显示图像、读出或写入图像相关的文件&#xff08;图像和视频&#xff09;、处理简单的鼠标…

【大数据之Hadoop】二十六、生产调优-HDFS集群压测

测试上传数据到集群和拉取数据的时间。HDFS的读写性能主要受网络和磁盘影响比较大。为了方便测试&#xff0c;将hadoop102、hadoop103、hadoop104虚拟机网络的带宽都设置为100Mbps。100Mbps/812.5M/s。 1 测试HDFS写性能 写测试原理&#xff1a;   向磁盘写测试文件&#x…

MySQL数据库——MySQL下载安装

&#xff08;1&#xff09;数据库相关概念&#xff1a; &#xff08;2&#xff09;MySQL数据库下载&#xff08;windows版&#xff09;: 下载地址&#xff1a;MySQL :: Download MySQL Installerhttps://dev.mysql.com/downloads/installer/MySQL :: Download MySQL Installer…

Python小姿势 - Python中的类型检查

Python中的类型检查 在Python中&#xff0c;类型检查是通过内置函数isinstance()来实现的。 isinstance() 函数用于判断一个对象是否是一个已知的类型&#xff0c;类似 type()。 isinstance() 与 type() 区别&#xff1a; type() 不会认为子类是一种父类类型。 isinstance() 会…

【Linux下】线程概念

文章目录 【Linux下】线程概念理解线程线程操作接口线程和进程线程和进程的关系代码验证 线程优点线程缺点 【Linux下】线程概念 理解线程 一般的书上都是这么描述线程的 线程&#xff1a;是在进程内部运行的一个执行分支&#xff0c;属于进程的一部分&#xff0c;粒度要比进…

简单搭建Fabric网络

Fabric网络的搭建分为两个阶段&#xff1a;生成网络拓扑和启动网络。在这里&#xff0c;我们假设要搭建一个具有一个orderer节点和两个peer节点的Fabric网络。 在生成网络拓扑之前&#xff0c;需要准备好以下文件&#xff1a; crypto-config.yaml&#xff1a;用于生成组织和节…

什么牌子蓝牙耳机好用不贵?国产性价比高的蓝牙耳机推荐

相较于有线耳机&#xff0c;无线蓝牙耳机更便携、功能更丰富&#xff0c;不用受到耳机孔与线的限制。那么&#xff0c;什么牌子的蓝牙耳机好用不贵&#xff1f;针对这个问题&#xff0c;我给大家推荐几款国产性价比高的蓝牙耳机&#xff0c;可以当个参考。 一、南卡小音舱Lite…

JAVA代码规范审查

JAVA代码规范审查 1. 添加必要的注释 所有的类都必须添加创建者和创建日期&#xff0c;以及简单的注释描述 方法内部的复杂业务逻辑或者算法&#xff0c;需要添加清楚的注释 一般情况下&#xff0c;注释描述类、方法、变量的作用 任何需要提醒的警告或TODO&#xff0c;也要注…

python基础语法1

基本语句 判断语句 1.if语句 if 语法格式: if 要判断的条件:条件成立时&#xff0c;要做的事情 -------------------------- 执行流程:判断条件为True就执行if的语句体.条件为False就执行if以外的代码. if 案例: age int(input(请输入年龄))print(-----开始-----) if ag…

测试遵循的原则

测试遵循的原则 软件测试是在规定的条件下对程序进行操作&#xff0c;以发现程序错误&#xff0c;衡量软件质量&#xff0c;并对其是否能满足设计要求进行评估的过程。软件测试的基本原则有助于测试人员进行高质量的测试&#xff0c;尽早尽可能多的发现缺陷&#xff0c;并负责跟…

【51单片机】:串口通信基础知识详解

学习目标&#xff1a; 串口通信的基础知识和设置详解。 学习内容&#xff1a;串口通信基础知识 并行通信&#xff1a;多条数据线将数据字节的各个位同时传送*缺点&#xff1a;1.电磁干扰 2.成本高 3.由于传输线较多&#xff0c;长距离传输成本高串口通信&#xff1a;将数据字节…

STL常用梳理——STACK、QUEUE

STL——适配器篇 1、ListSTL list 容器介绍list使用 2、适配器介绍3、Deque容器Stack、Queue适配器实现 1、List STL list 容器介绍 STL list 容器&#xff0c;又称双向链表容器&#xff0c;即该容器的底层是以双向链表的形式实现的。这意味着&#xff0c;list 容器中的元素可…

Lecture 11(Preparation):领域自适应 (Domain Adaptation)

Domain shift: Training and testing data have different distributions. Transfer learning&#xff1a;在A任务上学到的技能&#xff0c;可以被用在B任务上 Domain Adaptation的技术&#xff0c;可以看作是Transfer learning的一种 Domain Adaptation: 第一种情况&#xf…

栈和队列OJ题思路分享之括号匹配(C语言实现)

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:刷题分享⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你刷更多C语言和数据结构的题!   &#x1f51d;&#x1f51d; 栈和队列刷题分享 1. 前言&…