静态和动态内存分配 + 强类型和弱类型语言

87 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情 原文链接:fuelerhq

编译时

编译时将代码转换为可执行形式的前一个阶段,。在java中,.java文件在这个阶段被javac编译器转换为.class文件。

javac fileName.java

通过上面的命令会生成一个名为fileName的.class文件,它将 java 代码转换为更接近本机机器语言的字节码。

运行

这是执行 .class 文件的第二阶段。在这里,JVM(Java 虚拟机)中的 java 编译器会将这个 .class 文件(字节码)转换为我们的处理器可以理解的机器码(10101....)。

可以通过以下命令执行此操作 -

java fileName // omit the .class

通过这样做,代码的输出结果将打印在终端的控制台窗口上。

现在,让我们谈谈静态内存分配

静态内存分配

在编译期间分配的内存称为静态内存分配。分配的内存是固定的,或者说是在运行时不能更改。

public void getValue {

    int [] array = {1,2,3,4,5}; // this is static memory allocation.

    }

静态内存分配的缺点

大小是固定的,在运行时不能增加或减少。如果我们分配了一个巨大的大小并且没有完全使用它,我们最终将浪费内存,反之亦然,我们将耗尽内存,这称为堆栈溢出。因此,动态内存分配概念应运而生。

操作系统将内存分配给特定的应用程序或程序,下面是内存的体系结构。

分配给程序的内存

函数和局部变量存储在堆栈中。一小段堆栈内存分配给main()方法,也称为堆栈帧,如下所示。

让我们举个例子来彻底理解这一点——

// function with local variables a,b and z
public class DynamicMemory {
    public int getSum(int a, int b) { 
      int z = a + b;
      return z;
    }

    public static void main(String[] args) {

      DynamicMemory obj = new DynamicMemory();

      int x = 10;
      int y = 20;
      int sum = obj.getSum(x, y);

      System.out.println(“sum of 02 nos.= “ +sum);
  }
}

该程序的执行步骤 -

  1. main()方法连同局部变量 x、y 和 z 将存储在堆栈帧内存区域的堆栈中。
  2. getSum()函数及其局部变量 a 和 b 将存储在堆栈中。
  3. 现在 main 函数暂停,直到getSum()函数执行并返回一个值。
  4. 一旦getSum()函数执行并返回一个值,它将从堆栈帧中删除,并且main()方法将进入图片。
  5. 一旦main()也被执行,它将从堆栈中删除。现在堆栈是空的。

这个概念对于Recursion是必不可少的。

堆栈存储数据,直到函数执行。

在运行时或执行时分配内存的过程称为动态内存分配

堆是发生动态内存分配的内存段。与按上述定义的顺序分配和取消分配内存的堆栈不同,堆是随机发生分配和取消分配的内存段。

对象和实例变量存储在堆区。

DynamicMemory obj = new DynamicMemory(); // it will be stored in heap memory

新关键字

new关键字在 java 程序中做了三件事 -

  1. 它将在堆区域中保留一个内存空间,并将所有非静态成员加载到该区域中。
  2. 它将这个内存区域的位置地址分配给对象。(在这种情况下是 obj)。
  3. 如果你没有为字段(变量)分配任何值,那么new将为这些变量分配默认值。

强类型语言和弱类型语言

让我们最后一次把它说出来——Java 是一种强类型和静态类型的语言。

另一方面,JavaScript 是一种弱类型和静态类型的语言。

强类型语言意味着一旦声明了具有特定数据类型的变量,就不能将其他类型的数据分配给该变量。编译器将抛出不匹配类型的编译时错误。

例如

int numA = 10;
byte numB = 1;

int numC = numB; // this will be done implicitly

byte numD = numA; // this will throw a compile-time error

byte numD = (byte) numA; // correct code

换句话说,当你将“较宽”数据分配给“较窄”数据类型变量时,编译器不会进行隐式类型转换。必须明确地进行窄类型转换。