百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Java static关键字你了解多少? java中static关键字的用法

yuyutoo 2024-10-12 00:56 9 浏览 0 评论

文章目录

static关键字

1.static修饰成员变量

在引入static关键字之前呢,我们先看这样一个示例:

1)设计一个Peple类如下:

public class People {
 
    //实例变量
    private String name;
    private int age;
    private int count;//用来统计对象的生成个数

    //构造方法
    public People(String name, int age) {
 
        this.name = name;
        this.age = age;
        count++;
    }

    //实例方法
    public void work() {
 
        System.out.println("好好学习,年薪百万,迎娶白富美!");
    }
    
    public int getCount() {
 
        return count;
    }
}

2)设计一个TestDemo类如下:

public class TestDemo {
 
    public static void main(String[] args) {
 
        People people1 = new People("王昭君", 18);
        People people2 = new People("赵云", 20);
        People people3 = new People("安琪拉", 19);
        People people4 = new People("吕布", 21);
        People people5 = new People("貂蝉", 20);
    }
}

?在TestDemo中我们new了5个对象,调用了5次People类中的构造函数,那么count值为多少呢?因为每new一个对象,在堆上开辟一个对象,我们知道对象的内存布局分为三部分,对象头、实例变量、内存填充,在 Java new 一个对象在堆上开辟的内存大小 博客中有提及到,一个对象一份实例变量,所以我们虽然new了5个对象,只是在每个对象中实现了count++,count的值都为1;

?那么怎么用count来实现统计对象的个数呢?也就是让每个对象共用一份变量?这就要引入static关键字啦!

当类中的变量用static关键字来修饰的时候,变量就变成了静态变量。静态变量是随着类的字节码的加载而被加载进内存的,所以只要程序一启动运行到该类时就会被加载进内存,不管创建了多少个对象在内存中只存储一份,跟对象无关。它是保存在方法区当中的,无论多少个对象该静态变量在内存中都只有一份。

修改上述示例中的代码,count用static关键字来修饰。

People类

public class People {
 
    //实例变量
    private String name;
    private int age;
    private static int count;//用来统计对象的生成个数

    //构造方法
    public People(String name, int age) {
 
        this.name = name;
        this.age = age;
        count++;
    }

    //实例方法
    public void work() {
 
        System.out.println("好好学习,年薪百万,迎娶白富美!");
    }
    
    public int getCount() {
 
        return count;
    }
}

静态变量是使用类名直接调用的,在以前我们设计一个类,如果把类中的实例变量设为公有或默认包访问权限的情况下,是可以通过类生成的对象来访问的;而静态变量只和类有关,可以用类名来访问(在静态变量设为公有或默认包的情况下)

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

注意:静态变量是定义在类中,方法体外面的。如果你清楚JVM,应该知道局部变量是保存在栈中的,而静态变量是保存在方法区中的,局部变量出了方法就被栈回收了,而静态变量不会,所以局部变量前不能加static关键字。

2.static修饰方法

在写代码过程中,我们有没有发现有些方法是通过创建对象的方式调用的,如常见的在键盘上输入一个整数,Scanner scanner = new Scanner(System.in); scanner.nextInt();而有的方法是通过类名直接调用的,比如 Arrays.copyOf();那么什么情况下可以直接用类名调用而不用间接的通过对象呢?这就与static关键字修饰方法有关了。

看这样的一个栗子,把上述中static关键字修饰变量的示例中People类的getCount()方法设计成静态方法。

代码如下:

public class People {
 
    //实例变量
    private String name;
    private int age;
    public static int count;//用来统计对象的生成个数

    //构造方法
    public People(String name, int age) {
 
        this.name = name;
        this.age = age;
        count++;
    }

    //实例方法
    public void work() {
 
        System.out.println("好好学习,年薪百万,迎娶白富美!");
    }
    public static int getCount() {
 
        return count;
    }
    
}

在TestDemo测试类中用类名调用一下getcount方法:

public class TestDemo {
 
    public static void main(String[] args) {
 
        People people1 = new People("王昭君", 18);
        People people2 = new People("赵云", 20);
        People people3 = new People("安琪拉", 19);
        People people4 = new People("吕布", 21);
        People people5 = new People("貂蝉", 20);
        
        int sum = People.getCount();
        System.out.println(sum);
    }
}

运行结果:

同时也验证了,静态变量跟对象无关,只和类有关,测试类中产生了5个对象,每产生一个对象调用一次构造函数,count++;故最后count的值为5。

静态方法和实例方法的区别

在静态方法中不可以出现实例变量,而在实例方法中可以出现实例变量,也可以出现静态变量。

因为在实例方法中有隐含的this,举个栗子,在上述People类中添加一个实例方法eat;

public void eat() {
 
        this.name = "高富帅";
        count = 1;
    }

在实例方法中实例变量是否有this关键字都可以,因为实例方法会提供对象(this),就是指的是当前对象;当然在实例方法中也可以包含静态变量,静态变量不需要提供this,而实例方法会提供,静态变量要不要this就是它自己的事了,也就是给静态变量提供this,可以不要。

静态方法是不会提供this的,实例变量需要this,静态方法提供不了,故在静态方法中不能包含实例变量,如下:

3.类的初始化顺序

首先我们先引入静态块和实例块的概念,静态块是用来初始化静态变量的,实例块是用来初始化实例变量的。

设计一个A类如下:

public class A {
 
    //实例变量
    private int a;
    //静态变量
    private static int b;

    //静态块
    static {
 
        System.out.println("静态块");
    }
    //实例块
    {
 
        System.out.println("实例块");
    }
    //构造函数
    public A(){
 
        System.out.println("构造函数");
    }
}

为了能够在类的初始化顺序中看到实例变量和静态变量的初始化顺序,改进代码如下:

class B {
 
    public B() {
 
        System.out.println("实例变量");
    }
}
class C {
 
    public C() {
 
        System.out.println("静态变量");
    }
}
public class A {
 
    //实例变量
    private  B a = new B();
    //静态变量
    private static C b = new C();

    //静态块
    {
 
        System.out.println("静态块");
    }
    //实例块
    {
 
        System.out.println("实例块");
    }
    //构造函数
    public A(){
 
        System.out.println("构造函数");
    }
}

初始化实例变量a的时候必定会调用B类的构造函数,初始化静态变量b的时候必定会调用C类的构造函数。

在TestDemo测试类中生成A的对象,并查看运行结果。

public class TestDemo {
 
    public static void main(String[] args) {
 
        A aa = new A();
    }
}

运行结果:

通过运行结果可以发现,在生成对象,调用构造函数之前还搞了很多东西。

所以类的初始化的顺序静态变量、静态块、实例变量、实例块、构造函数

4.单例模式

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,也就是只能产生一个对象。

懒汉单例模式

懒汉单例模式:在第一次调用的时候实例化

1)产生对象首先需要在堆上开辟内存,然后调用构造函数来生成一个对象。如果把类的构造函数设为公有的,那么就可以随便new对象了,所以我们把构造函数设为私有的,此时把构造函数设为私有的就会产生在类外无法访问的问题,不能调用构造函数,就不能生成对象了。

2)那么就需要在类中提供一个方法,在类中生成对象,返回出去。那么问题又来了,没有生成对象,在类外怎么调用这个方法呢?这种情况下只能考虑用类名调用了,用类名调用该方法,就要把该方法设为静态方法,在该方法中调用构造函数生成对象,用一个该类的引用变量指向这个对象,但是如果把该引用变量定义在该类中,在类外多次调用该静态方法,还是会生成多个对象,所以不能把这个引用变量定义为局部变量,应该把它定义在方法外,又因为在静态方法中只能调用静态变量,所以把该变量定义为静态变量。

3)最后我们考虑,一开始该静态变量为空,调用静态方法生成对象,就会给该静态变量赋值一个地址,再次调用又会给它重新赋值新的地址,为了只能产生一个对象,我们需要在生成对象的静态方法中给定一个限定条件,当引用变量为空的时候才产生对象。

People类:

public class People {
 
    private static People p;
    //私有构造方法
    private People() {
 

    }

    public static People getInstance() {
 
         if (p == null) {
 
             p = new People();
         }
        return p;
    }
}

TestDemo类生成对象,类名调用方法。

public class TestDemo {
 
    public static void main(String[] args) {
 
        People p = People.getInstance();
    }
}

饿汉单例模式

饿汉单例模式:在类初始化时,已自行实例化

饿汉单例模式与懒汉单例模式不同的是实例化时期不同,代码如下:

People类:

public class People {
 
    //私有构造方法
    private People() {
 

    }

    //已经自行实例化
    private static People p = new People();
    public static People getInstance() {
 
        return p;
    }
}

TestDemo类生成对象,类名调用方法。

public class TestDemo {
 
    public static void main(String[] args) {
 
        People p = People.getInstance();
    }
}

相关推荐

墨尔本一华裔男子与亚裔男子分别失踪数日 警方寻人

中新网5月15日电据澳洲新快网报道,据澳大利亚维州警察局网站消息,22岁的华裔男子邓跃(Yue‘Peter’Deng,音译)失踪已6天,维州警方于当地时间13日发布寻人通告,寻求公众协助寻找邓跃。华...

网络交友须谨慎!美国犹他州一男子因涉嫌杀害女网友被捕

伊森·洪克斯克(图源网络,侵删)据美国广播公司(ABC)25日报道,美国犹他州一名男子于24日因涉嫌谋杀被捕。警方表示,这名男子主动告知警局,称其杀害了一名在网络交友软件上认识的25岁女子。雷顿警...

一课译词:来龙去脉(来龙去脉 的意思解释)

Mountainranges[Photo/SIPA]“来龙去脉”,汉语成语,本指山脉的走势和去向,现比喻一件事的前因后果(causeandeffectofanevent),可以翻译为“i...

高考重要考点:range(range高考用法)

range可以用作动词,也可以用作名词,含义特别多,在阅读理解中出现的频率很高,还经常作为完形填空的选项,而且在作文中使用是非常好的高级词汇。...

C++20 Ranges:现代范围操作(现代c++白皮书)

1.引言:C++20Ranges库简介C++20引入的Ranges库是C++标准库的重要更新,旨在提供更现代化、表达力更强的方式来处理数据序列(范围,range)。Ranges库基于...

学习VBA,报表做到飞 第二章 数组 2.4 Filter函数

第二章数组2.4Filter函数Filter函数功能与autofilter函数类似,它对一个一维数组进行筛选,返回一个从0开始的数组。...

VBA学习笔记:数组:数组相关函数—Split,Join

Split拆分字符串函数,语法Split(expression,字符,Limit,compare),第1参数为必写,后面3个参数都是可选项。Expression为需要拆分的数据,“字符”就是以哪个字...

VBA如何自定义序列,学会这些方法,让你工作更轻松

No.1在Excel中,自定义序列是一种快速填表机制,如何有效地利用这个方法,可以大大增加工作效率。通常在操作工作表的时候,可能会输入一些很有序的序列,如果一一录入就显得十分笨拙。Excel给出了一种...

Excel VBA入门教程1.3 数组基础(vba数组详解)

1.3数组使用数组和对象时,也要声明,这里说下数组的声明:'确定范围的数组,可以存储b-a+1个数,a、b为整数Dim数组名称(aTob)As数据类型Dimarr...

远程网络调试工具百宝箱-MobaXterm

MobaXterm是一个功能强大的远程网络工具百宝箱,它将所有重要的远程网络工具(SSH、Telnet、X11、RDP、VNC、FTP、MOSH、Serial等)和Unix命令(bash、ls、cat...

AREX:携程新一代自动化回归测试工具的设计与实现

一、背景随着携程机票BU业务规模的不断提高,业务系统日趋复杂,各种问题和挑战也随之而来。对于研发测试团队,面临着各种效能困境,包括业务复杂度高、数据构造工作量大、回归测试全量回归、沟通成本高、测试用例...

Windows、Android、IOS、Web自动化工具选择策略

Windows平台中应用UI自动化测试解决方案AutoIT是开源工具,该工具识别windows的标准控件效果不错,但是当它遇到应用中非标准控件定义的UI元素时往往就无能为力了,这个时候选择silkte...

python自动化工具:pywinauto(python快速上手 自动化)

简介Pywinauto是完全由Python构建的一个模块,可以用于自动化Windows上的GUI应用程序。同时,它支持鼠标、键盘操作,在元素控件树较复杂的界面,可以辅助我们完成自动化操作。我在...

时下最火的 Airtest 如何测试手机 APP?

引言Airtest是网易出品的一款基于图像识别的自动化测试工具,主要应用在手机APP和游戏的测试。一旦使用了这个工具进行APP的自动化,你就会发现自动化测试原来是如此简单!!连接手机要进行...

【推荐】7个最强Appium替代工具,移动App自动化测试必备!

在移动应用开发日益火爆的今天,自动化测试成为了确保应用质量和用户体验的关键环节。Appium作为一款广泛应用的移动应用自动化测试工具,为测试人员所熟知。然而,在不同的测试场景和需求下,还有许多其他优...

取消回复欢迎 发表评论: