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

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

yuyutoo 2024-10-12 00:56 5 浏览 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();
    }
}

相关推荐

深度解读Spring框架的核心原理

深度解读Spring框架的核心原理在Java开发的世界里,提到Spring框架,就像提起一位久经沙场的老将,它几乎成了企业级应用开发的代名词。那么,这个被无数开发者膜拜的框架究竟有何独特之处?今天,我...

「Spring认证」Spring 框架概述

Spring是最流行的企业Java应用程序开发框架。全球数以百万计的开发人员使用SpringFramework来创建高性能、易于测试和可重用的代码。Spring框架是一个开源的Java...

学习Spring框架 这一篇就够了

1.spring概述1.1Spring是什么(理解)...

Spring框架双核解析:IOC与AOP的本质与实战

#Spring核心#IOC容器#AOP编程#Java框架设计...

Spring Boot与传统Spring框架的对比:探索Java开发的新境界

SpringBoot与传统Spring框架的对比:探索Java开发的新境界在Java生态系统中,Spring框架无疑是一个里程碑式的存在。从最初的简单依赖注入容器,到如今覆盖企业级开发方方面面的庞大...

Spring MVC框架源码深度剖析:从入门到精通

SpringMVC框架源码深度剖析:从入门到精通SpringMVC框架简介SpringMVC作为Spring框架的一部分,为构建Web应用程序提供了强大且灵活的支持。它遵循MVC(Model-V...

Spring框架入门

一.spring是什么?Spring是分层...

程序员必知必会技能之Spring框架基础——面向切面编程!

面向切面编程AOP(AspectOrientedProgramming)与OOP(ObjectOrientedProgramming,面向对象编程)相辅相成。AOP提供了与OOP不同的抽象软件结...

Spring Security安全框架深度解读:为你的应用穿上“钢铁铠甲”

SpringSecurity安全框架深度解读:为你的应用穿上“钢铁铠甲”在现代网络世界里,保护我们的应用程序免受各种威胁攻击至关重要。而在这个过程中,SpringSecurity框架无疑是我们最可...

Spring框架的设计哲学与实现:打造轻量级的企业级Java应用

Spring框架的设计哲学与实现:打造轻量级的企业级Java应用Spring框架自2003年诞生以来,已成为企业级Java应用开发的代名词。它不仅仅是一个框架,更是一种设计理念和哲学的体现。本文将带你...

Spring框架深度解析:从核心原理到底层实现的全方位避坑指南

一、Spring框架核心概念解析1.控制反转(IoC)与依赖注入(DI)Spring的核心思想是通过IoC容器管理对象的生命周期和依赖关系。传统开发中,对象通过new主动创建依赖对象,导致高耦合;而S...

Java框架 —— Spring简介

简介一般来说,Spring指的是SpringFramework,它提供了很多功能,例如:控制反转(IOC)、依赖注入...

Spring 框架概述,模块划分

Spring框架以控制反转(InversionofControl,IoC)和面向切面编程(Aspect-OrientedProgramming,AOP)为核心,旨在简化企业级应用开发,使开发者...

spring框架怎么实现依赖注入?

依赖注入的作用就是在使用Spring框架创建对象时,动态的将其所依赖的对象注入到Bean组件中,其实现方式通常有两种,一种是属性setter方法注入,另一种是构造方法注入。具体介绍如下:●属性set...

Spring框架详解

  Spring是一种开放源码框架,旨在解决企业应用程序开发的复杂性。一个主要优点就是它的分层体系结构,层次结构让你可以选择要用的组件,同时也为J2EE应用程序开发提供了集成框架。  Spring特征...

取消回复欢迎 发表评论: