0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Java中对static关键词的介绍

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-10-11 15:26 次阅读

staticJava的一个关键字,可以用来修饰成员变量、修饰成员方法、构造静态代码块、实现静态导包以及实现静态内部类,下面我们来分别介绍。

1、修饰成员变量

用 static 修饰成员变量可以说是该关键字最常用的一个功能,通常将用 static 修饰的成员变量称为类成员或者静态成员,那么静态成员和不用 static 修饰的非静态成员有什么区别呢?

我们先看看不用 static 修饰的成员变量在内存中的构造。

package com.ys.bean;

/**
 * Create by YSOcean
 */
public class Person {
    private String name;
    private Integer age;

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
    //get和set方法省略
}

首先,我们创建一个实体类 Person,有两个属性 name 和 age,都是普通成员变量(没有用 static 关键字修饰),接着我们通过其构造方法创建两个对象:

Person p1 = new Person("Tom",21);
Person p2 = new Person("Marry",20);
System.out.println(p1.toString());//Person{name='Tom', age=21}
System.out.println(p2.toString());//Person{name='Marry', age=20}

这两个对象在内存中的存储结构如下:

图片
由上图可知,我们创建的两个对象 p1 和 p2 存储在堆中,但是其引用地址是存放在栈中的,而且这两个对象的两个变量互相独立,我们修改任何一个对象的属性值,是不改变另外一个对象的属性值的。

下面我们将 Person 类中的 age 属性改为由 static 关键字修饰:

package com.ys.bean;

/**
 * Create by YSOcean
 */
public class Person {
    private  String name;
    private static Integer age;

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
    //get和set方法省略

}

同样我们还是向上面一样,创建 p1 和 p2 两个对象,并打印这两个对象,看看和上面打印的有啥区别呢?

Person p1 = new Person("Tom",21);
Person p2 = new Person("Marry",20);
System.out.println(p1.toString());//Person{name='Tom', age=20}
System.out.println(p2.toString());//Person{name='Marry', age=20}

我们发现第三行代码打印的 p1 对象 age 属性变为 20了,这是为什么呢?

图片
这是因为用在 jvm 的内存构造中,会在堆中开辟一块内存空间,专门用来存储用 static 修饰的成员变量,称为静态存储区,无论我们创建多少个对象,用 static 修饰的成员变量有且只有一份存储在静态存储区中,所以该静态变量的值是以最后创建对象时设置该静态变量的值为准,也就是由于 p1 先设置 age = 21,后来创建了 p2 对象,p2将 age 改为了20,那么该静态存储区的 age 属性值也被修改成了20。

PS:在 JDK1.8 以前,静态存储区是存放在方法区的,而方法区不属于堆,在 JDK1.8 之后,才将方法区干掉了,方法区中的静态存储区改为到堆中存储。

总结:static 修饰的变量被所有对象所共享,在内存中只有一个副本。由于与对象无关,所以我们可以直接通过 类名.静态变量 的方式来直接调用静态变量。对应的非静态变量是对象所拥有的,多少个对象就有多少个非静态变量,各个对象所拥有的副本不受影响。

2、修饰修饰成员方法

用 static 关键字修饰成员方法也是一样的道理,我们可以直接通过 类名.静态方法名() 的方式来调用,而不用创建对象。

public class Person {
    private  String name;
    private static Integer age;

    public static void printClassName(){
        System.out.println("com.ys.bean.Person");
    }
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
    //get和set方法省略

}

调用静态方法:

Person.printClassName();//com.ys.bean.Person

3、静态代码块

用 static 修饰的代码块称为静态代码块,静态代码块可以置于类的任意一个地方(和成员变量成员方法同等地位,不可放入方法中),并且一个类可以有多个静态代码块,在类初次载入内存时加载静态代码块,并且按照声明静态代码块的顺序来加载,且仅加载一次,优先于各种代码块以及构造函数。

public class CodeBlock {
    static{
        System.out.println("静态代码块");
    }
}

由于静态代码块只在类载入内存时加载一次的特性,我们可以利用静态代码块来优化程序性能,比如某个比较大配置文件需要在创建对象时加载,这时候为了节省内存,我们可以将该配置文件的加载时机放入到静态代码块中,那么我们无论创建多少个对象时,该配置文件也只加载了一次。

4、静态导包

用 static 来修饰成员变量,成员方法,以及静态代码块是最常用的三个功能,静态导包是 JDK1.5以后的新特性,用 import static 包名 来代替传统的 import 包名 方式。那么有什么用呢?

比如我们创建一个数组,然后用 JDK 自带的 Arrays 工具类的 sort 方法来对数组进行排序:

package com.ys.test;

import java.util.Arrays;
/**
 * Create by YSOcean
 */
public class StaticTest {

    public static void main(String[] args) {
        int[] arrays = {3,4,2,8,1,9};
        Arrays.sort(arrays);
    }
}

我们可以看到,调用 sort 方法时,需要进行 import java.util.Arrays 的导包操作,那么变为静态导包呢?

package com.ys.test;

import static java.util.Arrays.*;
/**
 * Create by YSOcean
 */
public class StaticTest {

    public static void main(String[] args) {
        int[] arrays = {3,4,2,8,1,9};
        sort(arrays);
    }
}

我们可以看到第三行代码的 import java.util.Arrays 变为了 import static java.util.Arrays.*,意思是导入 Arrays 类中的所有静态方法,当然你也可以将 * 变为某个方法名,也就是只导入该方法,那么我们在调用该方法时,就可以不带上类名,直接通过方法名来调用(第 11 行代码)。

静态导包只会减少程序员的代码编写量,对于性能是没有任何提升的(也不会降低性能,Java核心技术第10版卷1第148页4.7.1章节类的导入有介绍),反而会降低代码的可读性,所以实际如何使用需要权衡。

5、静态内部类

首先我们要知道什么是内部类,定义在一个类的内部的类叫内部类,包含内部类的类叫外部类,内部类用 static 修饰便是我们所说的静态内部类。

定义内部类的好处是外部类可以访问内部类的所有方法和属性,包括私有方法和私有属性。

访问普通内部类,我们需要先创建外部类的对象,然后通过外部类名.new 创建内部类的实例。

package com.ys.bean;

/**
 * Create by hadoop
 */
public class OutClass {

    public class InnerClass{

    }
}
* OuterClass oc = new OuterClass();
  * OuterClass.InnerClass in = oc.new InnerClass();

访问静态内部类,我们不需要创建外部类的对象,可以直接通过 外部类名.内部类名 来创建实例。

package com.ys.bean;

/**
 * Create by hadoop
 */
public class OutClass {

    public static class InnerClass{

    }
}
OuterClass.StaticInnerClass sic = new OuterClass.StaticInnerClass();

6、常见问题

①、静态变量能存在于普通方法中吗?

能。很明显,普通方法必须通过对象来调用,静态变量都可以直接通过类名来调用了,更不用说通过对象来调用,所以是可以存在于普通方法中的。

②、静态方法能存在普通变量吗?

不能。因为静态方法可以直接通过类名来直接调用,不用创建对象,而普通变量是必须通过对象来调用的。那么将普通变量放在静态方法中,在直接通过类来调用静态方法时就会报错。所以不能。

③、静态代码块能放在方法体中吗?

不能。首先我们要明确静态代码块是在类加载的时候自动运行的。

普通方法需要我们创建对象,然后手工去调用方法,所静态代码块不能声明在普通方法中。

那么对于用 static 修饰的静态方法呢?同样也是不能的。因为静态方法同样也需要我们手工通过类名来调用,而不是直接在类加载的时候就运行了。

也就是说静态代码块能够自动执行,而不管是普通方法还是静态方法都是需要手工执行的。

④、静态导包会比普通导包消耗更多的性能?

不会。静态导包实际上在编译期间都会被编译器进行处理,将其转换成普通按需导包的形式,所以在程序运行期间是不影响性能的。

⑤、static 可以用来修饰局部变量吗?

不能。不管是在普通方法还是在静态方法中,static 关键字都不能用来修饰局部变量,这是Java的规定。稍微想想也能明白,局部变量的声明周期是随着方法的结束而结束的,因为static 修饰的变量是全局的,不与对象有关的,如果用 static 修饰局部变量容易造成理解上的冲突,所以Java规定 static 关键字不能用来修饰局部变量。

7、小结

好了,这就是Java中对 static 关键词的介绍,这下大家都清楚了吧,面向对象的漏网之鱼。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储
    +关注

    关注

    12

    文章

    3863

    浏览量

    84694
  • JAVA
    +关注

    关注

    19

    文章

    2904

    浏览量

    103018
  • 代码
    +关注

    关注

    30

    文章

    4557

    浏览量

    66845
  • static
    +关注

    关注

    0

    文章

    33

    浏览量

    10250
  • JDK
    JDK
    +关注

    关注

    0

    文章

    77

    浏览量

    16490
收藏 人收藏

    评论

    相关推荐

    [讨论]提高网站关键词排名的28个SEO小技巧

    ) 内容自然出现关键词 内容第一段和最后一段出现关键词 H1,H2标签中出现关键词 导出链接锚文本包含
    发表于 12-01 17:08

    请问DSP里如何确定ioport关键词定义的地址对应的引脚?

    请问DSP里如何确定ioport关键词定义的地址对应的引脚?
    发表于 06-28 15:48

    ☑网站建设 ☑网站推广 ☑关键词优化 ☑百度地标 ☑欢迎...

    ☑网站建设 ☑网站推广 ☑关键词优化 ☑百度地标 ☑欢迎咨询QQ:2991704102
    发表于 03-15 16:13

    TF-IDF测量文章的关键词相关性研究

    停用词的移除、大小写字母转化和词干提取。4)获取查询。获取单词权重,对于可疑文档利用TF-IDF获得关键词,并排序得到相应的关键词列表。排在前n个的关键词组成一个查询,以此类推,本试验
    发表于 01-26 10:38

    亚马逊代运营 amazon Search term 关键词填写的“神技”

    关键词稍作调整,以及筛选出的关键词在搜索结果的排名做出决定,是否应该放在 search term ;3.放一些与自己产品相关的长尾
    发表于 06-05 15:41

    HanLP关键词提取算法分析详解

    l 参考论文:《TextRank: Bringing Order into Texts》l TextRank算法提取关键词Java实现l TextRank算法自动摘要的Java实现这篇文章
    发表于 11-05 10:41

    基于Cortex-M处理器的高精度关键词识别实现

    我们可以对神经网络架构进行优化,使之适配微控制器的内存和计算限制范围,并且不会影响精度。我们将在本文中解释和探讨深度可分离卷积神经网络在 Cortex-M 处理器上实现关键词识别的潜力。关键词识别
    发表于 07-23 06:59

    关键词优化有哪些实用的方法

    的排名。还有一些实用的方法就是网站的一个关键词布局,这里应该设计seo算法的页面相关匹配程度,这样来提升网站页面的整体相关性,其次是重要的位置部署好我们要做的关键词,比如重要的一些标签来添加我们做
    发表于 08-11 01:19

    百度关键词排名掉完了怎么办

    一夜之间关键词排名掉完了,没有被K,也没有出现违规操作,这是怎么回事呢?
    发表于 01-27 11:01

    如何在Cortex-M处理器上实现高精度关键词的识别

    如何在 Cortex-M 处理器上实现高精度关键词识别
    发表于 02-05 07:14

    请问quartus有类似于vivado * ALLOW_COMBINATORIAL_LOOPS = "true"的关键词吗?

    我想在在verilog文件引入环,但是总是被quartus的综合优化掉,请问quartus有类似于vivado * ALLOW_COMBINATORIAL_LOOPS = "true"的关键词吗?
    发表于 01-07 11:10

    example/speech_recognition/asr样例写了一个关键词识别程序,关键词识别后播放提升音失败的原因?

    仿造example/speech_recognition/asr样例写了一个关键词识别程序,识别到关键词后,就播放提示音。目前关键词可以正确识别,就是播放提示音的时候就报错,报错信息如下,请各位帮忙
    发表于 03-10 06:18

    #2023,你的 FPGA 年度关键词是什么? #

    FPGA 年度关键词,我的想法是“标准化”;今年的工作遇到了不少同事的issues,本身都是小问题或者很细节的东西但是却反复出现问题,目前想到的最好的办法是做好设计规则的标准化才能避免,不知道大家有没有更好的建议?
    发表于 12-06 20:31

    javastatic的作用及常见的误区

    一.static关键字的用途 二.static关键字的误区 三。常见的笔试面试题 一.static关键
    发表于 09-27 10:44 0次下载
    <b class='flag-5'>java</b>中<b class='flag-5'>static</b>的作用及常见的误区

    javastatic关键字的作用

    列举了一些面试笔试中常见的关于static的考题。 以下是本文的目录大纲: 一.static关键字的用途 二.static关键字的误区 三。
    发表于 09-27 17:12 0次下载