为什么java中静态方法不能调用非静态方法和变量?

为什么java中静态方法不能调用非静态方法和变量?
很多人在之前的学习之前总是会去死记硬背一些概念,随手写了一个经常会碰到的问题,欢迎大家参考

我们先看效果 --静态方法去调用非静态的成员—>报错
为什么java中静态方法不能调用非静态方法和变量?_第1张图片
静态的main方法–程序的运行入口都会出错,那么程序肯定是运行不了,我们换个角度–非静态调用静态资源

为什么java中静态方法不能调用非静态方法和变量?_第2张图片
非静态调用静态资源没有任何问题,怎么回事呢?其实这和JAVA中的类的加载有关系:
原因:因为类中的资源是属于类的对象,和类是平级,属于类,而此时不属于类的对象,我们从JVM的类的加载说起

一个类从编译到运行结束如下过程:
为什么java中静态方法不能调用非静态方法和变量?_第3张图片加载进入内存中:主要做了三件事

  1. JVM通过类的全限定类名来获取该类的二进制字节流-class文件
  2. 将这个字节流文件中所代表的静态存储数据结构转化为方法区可以运行时的数据结构
  3. 在堆中生成一个该类class对象引用(一个类只能生成一个class对象,因为类只会被加载一次),作为访问方法区的数据访问入口
    注意此时会扫描我们编写的程序代码中是否存在静态资源(静态资源–静态变量 静态方法,静态代码块,静态内存类等)此时还没有进行内存的分配

验证:主要作用就是保证类的语法等结构是否能正确的被加载的过程,保证符合JVM的规范,不会给JVM造成危害。如果验证失败,就会抛出一个java.lang.VerifyError异常或其子类异常。验证过程分为四个阶段

  1. 文件格式的验证:保证class文件字节流能被JVM虚拟机正确加载使用
  2. 元数据的验证:保证class字节流文件的语义信息正确,没有语法错误,符合java语言的规范
  3. 字节码验证:保证在运行时加载的数据流和控制流信息正确,在校验类的时候不会危害到虚拟机
  4. 符号引用验证:保证在class文件中的符号引用直接转化成直接引用的时候,校验引用的正确性,正确的被转成直接引用

准备:此时将会根据我们代码中扫描所得到的的静态资源进行分配内存并给予相应的默认初始值此时便为静态资源分配了内存,但是非静态资源(变量,方法,构造代码块等)还没有进行内存的分配

解析:解析的过程是将常量池中的符号引用转换为直接引用,主要包括四种类型引用的解析,类或接口的解析,方法的解析,字段解析,接口方法的解析。进行常量池的符号引用–直接引用

初始化:终于来了,原来初始化之前还有这么多操作,一定要熟记。

  1. 初始化阶段进行类中的各种变量进行赋予初始值(static除外)
  2. 由前面我们知道,静态资源(变量)在之前类加载的连接中已经被初始化赋予了初始的默认值所以这个时候在虚拟机中静态资源已经被加载了,此时可以根据程序员的需求进行值的覆盖,赋予相应的值满足开发的需求
  3. 在初始化的时候我们才可以为普通成员变量进行赋值(系统的默认值,或者一开始已经赋给的值)
  4. 可以通过类名去访问静态资源,而不可以通过对象去访问静态资源,因为只有在类的对象的初始化之后才会给非静态成员变量分配内存,初始化值

所以答案就是:
静态资源是属于类的,只能由类或者类的静态资源调用静态资源,而非静态资源(变量,方法)是属于类对象的,只有对象初始化后才存在,如果使用静态方法去调用非静态的资源,那可就会造成资源还没准备好就直接去调用的矛盾,存在越界调用,当然不可以这样了。

你可能感兴趣的:(问题答疑区,java,jvm,编程语言,python,linux)