Java 中的 static:静态变量、静态方法,一切都在掌握中

这篇具有很好参考价值的文章主要介绍了Java 中的 static:静态变量、静态方法,一切都在掌握中。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🎏:你只管努力,剩下的交给时间

🏠 :小破站

前言

static,这个小小的关键字在Java中扮演着重要的角色,但它的用途和工作原理可能会让人感到困惑。你是否曾想过为什么有些方法和变量可以直接从类访问,而无需创建实例?或者为什么某些变量在多个实例之间共享相同的值?在本文中,我们将探索static的奥秘,深入了解它的各种用法,从静态方法的调用到静态变量的共享,让你对Java中的static有一个清晰的认识。

第一:静态方法

静态方法(Static Method)是属于类而不是类的实例的方法。它可以在不创建类的实例的情况下被调用。静态方法通常用于执行与类相关的操作,而不需要访问或修改特定实例的状态。

以下是关于静态方法的声明、调用以及与实例方法的区别:

声明静态方法

在Java中,声明静态方法需要使用static关键字。静态方法可以直接属于类,而不是类的实例。

public class MyClass {
    public static void myStaticMethod() {
        // 静态方法的代码
    }
}

调用静态方法

你可以通过类名来调用静态方法,而不需要创建类的实例。

MyClass.myStaticMethod();

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

  1. 关联性:静态方法与类本身相关,而实例方法与类的实例相关。

  2. 调用方式:静态方法通过类名调用,而实例方法需要通过对象实例来调用。

  3. 访问权限:静态方法可以访问类的静态成员,但不能访问非静态成员(实例成员)。实例方法可以访问类的静态和非静态成员。

  4. 内部引用:静态方法中不能使用this关键字,因为它没有当前对象的引用。实例方法可以使用this来引用当前对象。

  5. 生命周期:静态方法在类加载时初始化,而实例方法在对象创建时初始化。

总之,静态方法是与类本身相关的方法,通常用于执行通用操作或访问静态成员。实例方法则是与类的实例相关的方法,可以访问和修改实例的状态。选择使用静态方法还是实例方法取决于你的需求和代码设计。

第二:静态变量

静态变量,也称为类变量,是属于类而不是类的实例的变量。它在类加载时被初始化,只有一个副本,被所有类的实例共享。静态变量通常用于存储类级别的数据,它们不依赖于特定对象的状态,而是与整个类相关联。

以下是有关静态变量的声明、使用、生命周期和作用域的信息:

声明静态变量

在Java中,声明静态变量需要使用static关键字。静态变量通常位于类的顶部,通常在类内部,方法外部进行声明。静态变量通常用public, private, 或 protected等修饰符修饰。

public class MyClass {
    // 静态变量声明
    public static int staticVariable;
    private static String name;
}

使用静态变量

你可以通过类名来访问静态变量,也可以通过类的实例来访问它。通常建议使用类名来访问静态变量,因为它们与类相关联,而不是与特定对象实例相关。

MyClass.staticVariable = 42; // 通过类名访问静态变量
int value = MyClass.staticVariable; // 通过类名获取静态变量的值

MyClass myObject = new MyClass();
myObject.staticVariable = 10; // 也可以通过对象实例访问静态变量

静态变量的生命周期

静态变量的生命周期与类的生命周期相同。它们在类加载时初始化,一直存在,直到程序结束或类被卸载。静态变量的值在类加载后保持不变,因为它们是类级别的,而不是与对象实例相关联。

静态变量的作用域

静态变量在整个类中可见,它们的作用域覆盖整个类。可以在类的任何方法内部或外部访问静态变量。

总之,静态变量是属于类的,而不是类的实例的变量。它们在类加载时初始化,具有全局作用域,用于存储类级别的数据。静态变量通常用于存储不依赖于特定对象实例的信息,如常量值、计数器等。

第三:静态块

静态初始化块是Java中的一种特殊的块,用于在类加载时执行静态初始化操作。静态初始化块通常用于执行一些与静态成员变量相关的初始化任务,或在类加载时执行一些必要的设置。

以下是关于静态初始化块的用途和如何使用它来初始化静态变量的信息:

静态初始化块的用途

  1. 初始化静态变量:静态初始化块可以用于初始化静态变量,通常在静态变量的初始值不能直接赋值时使用。

  2. 执行复杂初始化逻辑:如果静态变量的初始化需要复杂的逻辑或依赖于其他类的加载,可以在静态初始化块中执行这些操作。

  3. 资源管理:静态初始化块可以用于管理资源,如数据库连接或文件句柄的初始化和释放。

如何使用静态块初始化静态变量

在Java中,你可以在类中使用静态初始化块,它以static {}的形式定义,包含初始化代码。

public class MyClass {
    // 静态变量声明
    public static int staticVariable;

    // 静态初始化块
    static {
        // 执行初始化操作
        staticVariable = 42;
    }
}

在上述示例中,静态初始化块在类加载时执行,并初始化了静态变量staticVariable的值为42。静态初始化块允许你执行更复杂的逻辑,如根据条件初始化静态变量,执行多步骤的初始化等。

请注意,静态初始化块只在类加载时执行一次,因此它适合用于一次性的初始化操作。如果你有多个静态初始化块,它们会按照在类中的顺序执行。

第四:静态内部类

静态内部类是嵌套在另一个类中的类,但它是一个静态类,与外部类的实例无关。静态内部类可以在不创建外部类实例的情况下被实例化,并可以访问外部类的静态成员,但不能访问外部类的非静态成员。

静态内部类的主要特点包括:

  1. 它被声明为静态(使用static关键字)。
  2. 它不能访问外部类的非静态成员(即实例成员)。
  3. 它可以访问外部类的静态成员和方法。
  4. 静态内部类的实例化不依赖于外部类的实例。

静态内部类的用途

静态内部类常用于以下情况:

  1. 封装:将一组相关的类封装在一个类内部,以减少命名冲突,提高代码的组织性和可读性。

  2. 工厂模式:静态内部类可用于实现工厂模式,其中外部类充当工厂,而静态内部类作为工厂方法。

  3. 单例模式:静态内部类通常用于实现懒加载的单例模式,因为它在需要时才加载并初始化。

  4. 优化类结构:将一些与外部类不直接关联但与其有某种联系的类组织在一起,以减少类的数量和提高代码可维护性。

示例

下面是一个示例,展示了如何使用静态内部类:

public class OuterClass {
    private static int outerStaticVariable = 42;

    // 静态内部类
    public static class StaticInnerClass {
        public void printOuterStaticVariable() {
            System.out.println("Outer static variable: " + outerStaticVariable);
        }
    }

    public static void main(String[] args) {
        // 创建静态内部类的实例
        StaticInnerClass inner = new StaticInnerClass();
        inner.printOuterStaticVariable();
    }
}

在这个示例中,StaticInnerClass是一个静态内部类,它可以访问外部类OuterClass的静态成员outerStaticVariable,但不能访问非静态成员。这允许你将相关的类组织在一起,提高了代码的可读性。

第五:静态导入

静态导入是Java中的一项特性,它允许你在代码中直接引用类的静态成员,而不需要显式指定类名。静态导入的主要目的是简化代码,提高可读性,减少重复的类名引用。

静态导入的目的和使用场景

  1. 简化代码:静态导入可以简化代码,特别是当你频繁使用某个类的静态方法或常量时,省去了重复输入类名的麻烦。

  2. 提高可读性:通过静态导入,你可以更清晰地表达代码的意图,减少了冗长的类名前缀,提高了可读性。

  3. 避免命名冲突:在某些情况下,静态导入还可以帮助避免命名冲突,因为你可以选择性地导入需要的静态成员,而不会污染命名空间。

如何使用静态导入简化代码

假设有一个名为MathUtil的类,其中包含了一些静态方法和常量:

public class MathUtil {
    public static int add(int a, int b) {
        return a + b;
    }

    public static final double PI = 3.14159265359;
}

使用静态导入,你可以在代码中直接引用这些静态方法和常量,而不需要显式指定类名:

import static com.example.MathUtil.*;

public class Main {
    public static void main(String[] args) {
        int result = add(5, 3); // 不需要写 MathUtil.add
        double circleArea = PI * 5 * 5; // 不需要写 MathUtil.PI
        System.out.println("Result: " + result);
        System.out.println("Circle Area: " + circleArea);
    }
}

在上述示例中,使用import static语句导入了MathUtil类的静态方法和常量,使得在Main类中可以直接使用它们,而不需要写类名前缀。

需要注意的是,尽量避免滥用静态导入,只导入必要的静态成员,以确保代码的可读性。

第六:单例模式

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一种访问该实例的全局点。使用静态变量可以很容易实现单例模式。

以下是如何使用静态变量实现单例模式的示例代码:

public class Singleton {
    // 使用静态变量来存储单例实例
    private static Singleton instance;

    // 私有构造方法,防止外部实例化
    private Singleton() {
    }

    // 公共静态方法,用于获取单例实例
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

上述代码中,Singleton类的构造方法是私有的,这意味着外部类无法直接实例化它。而通过getInstance方法,你可以获取Singleton类的单一实例。这个实例是通过静态变量instance来存储的,只有在第一次调用getInstance方法时才会创建。以后的调用都会返回同一个实例。

线程安全问题和解决方法

上述的单例模式示例是基本的单例模式,但它不是线程安全的。当多个线程同时访问getInstance方法时,可能会创建多个实例。为了确保线程安全,有几种解决方法:

  1. 饿汉式单例(Eager Initialization):在类加载时就创建单例实例,确保线程安全,但可能会导致资源浪费。

    public class Singleton {
        private static final Singleton instance = new Singleton();
        private Singleton() {
        }
        public static Singleton getInstance() {
            return instance;
        }
    }
    
  2. 双重检查锁定(Double-Check Locking):在第一次获取实例时加锁,之后的访问不需要再加锁,提高性能。

    public class Singleton {
        private static volatile Singleton instance;
        private Singleton() {
        }
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    
  3. 静态内部类:使用静态内部类来延迟加载单例实例,利用类加载机制确保线程安全。

    public class Singleton {
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
        private Singleton() {
        }
        public static Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }
    

这些是一些常见的单例模式的线程安全实现方式。选择哪种方式取决于项目的需求和性能考虑。最常用的是双重检查锁定和静态内部类方式,它们都是线程安全且延迟加载的。

第七:常见问题和最佳实践

静态成员的生命周期和线程安全性、避免滥用static的最佳实践以及静态变量的命名规范是编写高质量Java代码时需要考虑的关键问题。以下是这些问题的详细解释和最佳实践:

静态成员的生命周期和线程安全性

  • 生命周期:静态成员在类加载时初始化,生命周期与应用程序的运行时间相同。它们只会初始化一次。

  • 线程安全性:静态成员是全局共享的,因此可能存在线程安全问题。如果多个线程同时访问和修改静态成员,你需要采取适当的措施确保线程安全,如使用同步或其他并发控制机制。

避免滥用static的最佳实践

  1. 不必要的静态:避免在类中过度使用静态成员。只有当数据需要被类的所有实例共享时,才应该将其定义为静态。避免将每个成员都声明为静态,这会导致不必要的全局状态。

  2. 全局变量的谨慎使用:避免过度使用静态变量作为全局状态。全局变量可以使代码更难理解、调试和维护。尽量将变量的作用范围限制在需要的最小范围内。

  3. 静态方法的明智使用:静态方法通常用于实用工具类、工厂方法、单例模式等情况,但不应滥用。确保它们的使用合理,而不是为了方便而将所有方法都定义为静态。

静态变量的命名规范

  • 静态变量的命名通常采用大写字母,单词之间使用下划线分隔,以增加可读性。例如:MAX_VALUE, DEFAULT_TIMEOUT.

  • 静态变量应该是恒定不变的,不应该在运行时改变其值。如果静态变量需要修改,通常会使用final关键字声明。

  • 静态常量(如枚举的常量)通常使用全大写字母,单词之间使用下划线分隔,以表示它们是不可变的。例如:RED, GREEN.

总之,静态成员的生命周期与类加载相同,线程安全性需要注意。避免滥用static,只有在必要时才使用。在命名静态变量时,遵循命名规范,使用大写字母和下划线以提高可读性。

第八:案例研究

在实际项目中,static关键字经常用于各种场景,以下是一些示例说明如何在实际项目中使用static

  1. 常量定义static常量通常用于定义不变的常量,以避免魔法数字和提高代码可读性。例如,在一个几何计算库中,可以定义static final常量来表示圆周率π:

    public class MathConstants {
        public static final double PI = 3.14159265359;
    }
    
  2. 工具类:静态方法和静态变量通常用于工具类,这些类提供一组静态方法来执行通用任务。例如,java.lang.Math类中的所有方法都是静态的,用于执行数学运算。

    double result = Math.sqrt(16.0); // 调用静态方法
    
  3. 单例模式:静态变量常用于实现单例模式,确保只有一个类的实例。在单例类中,通常会有一个私有静态变量来存储单例实例。

    public class Singleton {
        private static Singleton instance;
        private Singleton() {
        }
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    
  4. 静态内部类:静态内部类常用于实现延迟加载的单例模式,它充当了工厂并实现了懒加载。

    public class Singleton {
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
        private Singleton() {
        }
        public static Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }
    
  5. 静态工厂方法:静态工厂方法通常用于创建对象实例,而不是使用构造方法。例如,java.util.Collections类提供了许多静态工厂方法用于创建不可变集合。

    List<String> unmodifiableList = Collections.unmodifiableList(originalList);
    
  6. 缓存:静态变量可以用于缓存数据,以提高性能。例如,你可以使用静态Map来缓存计算结果,以避免重复计算。

    public class MathCache {
        private static Map<Integer, Double> squareRootCache = new HashMap<>();
        public static double getSquaredRoot(int number) {
            if (!squareRootCache.containsKey(number)) {
                double result = Math.sqrt(number);
                squareRootCache.put(number, result);
            }
            return squareRootCache.get(number);
        }
    }
    

这些示例展示了在实际项目中使用static关键字的常见场景,包括定义常量、创建工具类、实现单例模式、实现静态内部类、提供静态工厂方法和使用缓存。static在这些场景中有助于提供全局状态、提高性能和提供工具方法。文章来源地址https://www.toymoban.com/news/detail-755872.html

到了这里,关于Java 中的 static:静态变量、静态方法,一切都在掌握中的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 4.【CPP】入门(初始化列表||explicit||static||友元||静态成员变量/函数)

    我们知道在c++11中才能在成员对象声明时初始化,像下面这样。 注意:构造函数不是初始化,而是赋初始值。那么在c++11以前该怎么初始化成员变量呢? 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次) 类中包含以下成员,必须放在初始化列表位置进行初始

    2024年01月20日
    浏览(42)
  • c++中static静态成员变量和静态成员函数、explcit和隐式类型转换、友元函数()详解

    声明为 static 的类成员 称为 类的静态成员 ,用 static 修饰的 成员变量 ,称之为 静态成员变量 ;用 static 修饰 的 成员函数 ,称之为 静态成员函数 。 静态成员变量一定要在类外进行初始化   静态成员 为 所有类对象所共享 ,不属于某个具体的对象,存放在静态区   静态成

    2024年02月04日
    浏览(49)
  • C++中的static(静态)

    2014年1月19日   内容整理自The Cherno:C++系列 2014年1月20日   内容整理自《程序设计教程:用C++语言编程 第三版》 陈家骏  郑滔 --------------------------------------------------------------------------------------------------------------------------------- static在C++中有2个意思,这取决于上下文

    2024年01月22日
    浏览(34)
  • 我在VScode学Java类与对象(Java显式参数和隐式参数、静态方法+main方法、Java访问修饰符、static关键字、Java的包、对象数组)第三辑

    我的个人博客主页:如果’\\\'真能转义1️⃣说1️⃣的博客主页 关于Java基本语法学习----可以参考我的这篇博客:《我在VScode学Java》 方法会操作对象并访问他们的实例字段。 在Java中,显式参数和隐式参数是方法调用中的两种不同类型的参数。 注释: 第7行: sum 方法的参数

    2024年02月16日
    浏览(96)
  • 探索Java中的静态变量与实例变量:存储区域、生命周期以及内存分配方式的区别

    🎉欢迎来到Java面试技巧专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:Java面试技巧 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 在Java中,静态变量

    2024年02月12日
    浏览(30)
  • 静态内部类的访问方法(static/无static)

    笔记汇总: 《Java面向对象程序设计》学习笔记 用static修饰内部类,可以直接通过内部类类名访问静态内部类。 没有用static修饰内部类,则需要new一个外部类实例,再通过外部实例创建内部类。 外部类之外创建内部类对象_new通过外部类创建内部类对象_Dingwensheng1222的

    2024年02月14日
    浏览(43)
  • 使用Mockito模拟Static静态方法

    Mockito3.4.0版本之后增加了对Static方法的支持,在这里简单记录下Mockito.mockStatic方法的用法 这是待测试的方法,用到了TestUtil.getString这个静态方法,将使用Mockito改变他的返回值 测试方法使用到的静态方法 他返回字符串本身,我们将通过Mockito改变他的返回值 Junit测试代码,执

    2024年02月02日
    浏览(39)
  • Java---类、static(静态)详解

    类的定义格式如下: 例如: 例如: 1.3.1 封装的步骤 使用 private 来修饰成员变量。 使用 public 修饰getter和setter方法。 1.3.2 封装的步骤实现 1.private修饰成员变量 2.public修饰getter和setter方法         static是静态的意思。 static可以修饰成员变量或者修饰方法。         

    2024年02月08日
    浏览(41)
  • java static修饰的静态成员

    静态成员 特点 : 静态方法的 注意事项 : 这里的 school 被 static 修饰   在这里我们 new 了两个对象,但是我们在第二个new的对象 s2 中没有输入学校,school应该为 null ,但是显然有数据,那是因为我们的 static 修饰了school. 学的不是技术,更是梦想!!!

    2024年02月15日
    浏览(33)
  • 深入理解C++中的静态(Static)关键字及其应用场景

    在C++中,静态(Static)是一个常见且重要的概念,用于描述变量、函数和类成员。它具有独特的特性和作用域,可以在不同的应用场景中发挥重要作用。本文将详细讨论C++中的静态,包括静态变量、静态函数和静态类成员,并对其与全局变量之间的区别进行分析

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包