首页 > 编程语言 >Java static关键字讲解

Java static关键字讲解

时间:2024-01-08 14:06:11浏览次数:40  
标签:Java 静态 成员 关键字 实例 static 内存 静态方法 方法


Java内存模型的简化视图:

  • 堆内存(Heap):存储所有的对象实例以及数组。无论是哪个线程创建的对象,都存储在堆内存中。
  • 栈内存(Stack):每个线程运行时都会创建自己的栈,用于存储局部变量(包括方法的参数)和控制方法调用的执行流。局部变量可能包括对堆内存中对象的引用。
  • 方法区(Method Area,在JDK 8及之后被称为元空间 Metaspace):存储每个类的结构信息,如运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容等。
  • 程序计数器(Program Counter):每个线程都有自己的程序计数器,是当前线程所执行的字节码的行号指示器。
  • 本地方法栈(Native Method Stack):为虚拟机使用到的Native方法服务。

在Java中,static 关键字确实表示静态的含义,用来定义属于类本身而不是类的某个特定实例的成员。静态成员包括静态变量(也称为类变量)和静态方法。这些静态成员在类被加载时初始化,并且只初始化一次。

在JDK 7以前,静态成员是存储在方法区中的,这部分内存区域用于存放类信息、常量、静态变量等。但从JDK 7开始,字符串常量池已经从方法区移动到了Java堆中。而在JDK 8及之后,方法区的概念已经被元空间(Metaspace)所取代,元空间使用的是本地内存,而不是虚拟机内存。

因此,静态成员现在应该被认为是存储在元空间中,而不是堆内存或堆区的静态区。元空间中存储了类的元数据、直接引用的对象(如类的静态字段)等信息。至于非静态成员,它们依然是存储在堆内存中,每个实例都有自己的一份拷贝。

问题:为什么静态方法不能调用非静态成员和方法,只能调用静态成员和方法?

首先,需要了解Java中静态(static)和非静态(也称为实例)成员的区别:

  1. 静态成员(包括静态方法和静态属性)属于类本身,而不是类的任何特定实例。这意味着静态成员是在类被加载到JVM时初始化的,存储在Java的方法区(在某些JVM实现中也被称为静态区或永久代),并且它们可以通过类名直接访问,而不需要创建类的实例。
  2. 实例成员(包括实例方法和实例属性)属于类的特定实例。每次使用new关键字创建类的新实例时,都会为这些成员分配内存,它们存储在堆内存中,并且必须通过类的实例来访问。

现在来看静态方法和实例成员之间的关系:

  • 静态方法可以直接访问类中的其他静态成员,因为它们都属于类层面,不需要类的实例即可存在。
  • 静态方法不能直接访问类中的实例成员,因为实例成员需要依附于具体的对象实例。如果静态方法要访问实例成员,它必须通过一个对象的引用来做到这一点。

这里的关键点是“直接访问”。实际上,静态方法是可以调用实例方法和访问实例属性的,但前提是它们必须通过一个对象的引用来进行。例如:

public class MyClass {
    private int instanceVar;

    public MyClass(int instanceVar) {
        this.instanceVar = instanceVar;
    }

    public void instanceMethod() {
        System.out.println("这是一个实例方法。");
    }

    public static void staticMethod(MyClass obj) {
        // 通过传入的对象引用调用实例方法
        obj.instanceMethod();
        
        // 通过传入的对象引用访问实例属性
        System.out.println("实例变量的值为:" + obj.instanceVar);
    }
}

public class Test {
    public static void main(String[] args) {
        MyClass obj = new MyClass(10);
        MyClass.staticMethod(obj); // 调用静态方法,并传入对象引用
    }
}

需要注意的是,实际上每一个成员方法中虚拟机会自动加入一个参数,(类名 this)这样可以直接调用其他的成员属性和方法,也可以调用静态属性和方法。

标签:Java,静态,成员,关键字,实例,static,内存,静态方法,方法
From: https://blog.51cto.com/u_16426526/9143908

相关文章

  • JavaScript WebAPI(三)(详解)
    这次介绍一下webAPI中的一些知识:回调函数回调函数是指如果将函数A做为参数传递给函数B时,我们称函数A为回调函数例如://立即执行函数中传递的函数是一个回调函数(function(){console.log("我是回调函数")})();//监听事件中传递的参数是一个回调函数constdiv=document......
  • JavaScript WebApi(二) 详解
    监听事件介绍事件监听是一种用于在特定条件下执行代码的编程技术。在Web开发中,事件监听器可以用于捕获和响应用户与页面交互的各种操作,如点击、滚动、输入等。事件监听的基本原理是,通过在特定元素上注册事件监听器,当事件在该元素上触发时,相应的处理函数会被执行。以下是事件监听的......
  • Java中子类都继承父类的什么?
    1.构造方法构造方法不可以被继承的,为什么呢?应为名称的定义,构造方法是一类名称与类名一致,无返回值和类型修饰的一种。所以如果子类继承父类的构造方法的话,那么就违背了构造方法的规定。2.成员属性成员属性是可以被继承的,我们要知道,当使用实例化子类的时候,使用new关键字创建子类实例......
  • JavaScript WebApi 一(详讲)
    基础知识在前面的部分已经讲过了,大家如果没有学习过JavaScript的可以去看一下1.DOM引入在JavaScript中,DOM(文档对象模型)提供了一种表示和操作HTML文档的方式。在DOM中,文档被表示为一个由节点组成的树形结构。DOM对象则是这些节点的抽象表示,它们可以通过JavaScript来访问和操作。DOM......
  • 详解Java死锁-检测与解决
    第1章:引言大家好,我是小黑,咱们今天来聊聊死锁。特别是对于咱们这些Java程序员来说,死锁就像是隐藏在暗处的陷阱,稍不注意就会掉进去。但别担心,小黑今天就来带大家一探究竟,看看怎么样才能避免这个陷阱。什么是死锁?简单来说,死锁就是两个或多个进程互相等待对方释放资源,结果大家都动......
  • Java中的InputStream和OutputStream详解
    引言在Java编程中,处理输入输出是日常任务的一部分,而流(Stream)是实现输入输出的核心概念。在JavaI/OAPI中,InputStream和OutputStream是所有字节流类的基础。本文将详细介绍这两个类及其在Java中的应用。什么是InputStream和OutputStream?InputStream是JavaI/O库中的一个抽象类,它......
  • 使用Jsoup的Java网络爬虫示例:抓取在线考试平台试题数据
    网络爬虫是一种强大的工具,用于从互联网上收集信息。而在Java中,Jsoup是一款常用的HTML解析库,提供了便捷的API来解析、提取和操作HTML数据。在本文中,我们将深入探讨如何利用Jsoup库构建一个Java网络爬虫,并使用代理服务器来抓取在线考试平台的试题数据。介绍Jsoup和网络爬虫首先,我们将......
  • Java医院医学AI智能导诊系统源码
    医院智能导诊系统是一款基于人工智能和大数据技术开发的医疗辅助软件,旨在为患者提供更加便捷、精准的医疗服务。一、什么是智能导诊系统?智能导诊系统是一种基于人工智能和大数据技术开发的医疗辅助软件,它能够通过对患者的症状、病史等信息进行计算分析,快速推荐科室和医生。通过简......
  • Java之序列化的详细解析
     3.序列化3.1概述Java提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反......
  • 详解Java中的原子操作
    第1章:什么是原子操作大家好,我是小黑,面试中一个经常被提起的话题就是“原子操作”。那么,到底什么是原子操作呢?在编程里,当咱们谈论“原子操作”时,其实是指那些在执行过程中不会被线程调度机制打断的操作。这种操作要么完全执行,要么完全不执行,没有中间状态。这就像是化学里的原子,不......