Java学习笔记——从数据类型到参数传递

一、Java数据类型

程序中的数据都属于某一特定类型,数据类型决定了数据的表示方式、取值范围及可进行的操作。Java数据类型分为基本数据类型和引用类型。

(一)、8种基本数据类型

基本数据类型是由一种简单数据组成的基本类型,其数据是不可分解的,可以直接参与该类型所允许的运算。Java提供了8种基本数据类型,包括6种数字类型(4个整数型,2个浮点型),一种字符类型,一种布尔型,如下所示:

类型名称关键字占用内存取值范围
字节型byte1 字节-128~127
短整型short2 字节-32768~32767
整型int4 字节-2147483648~2147483647
长整型long8 字节-9223372036854775808L~9223372036854775807L
单精度浮点型float4 字节+/-3.4E+38F(6~7 个有效位)
双精度浮点型double8 字节+/-1.8E+308 (15 个有效位)
字符型char2 字节ISO单一字符集
布尔型boolean1 字节true 或 false

(二)、引用数据类型

在Java中,除前面的8种基本数据类型以外都是引用数据类型。引用数据类型建立在基本数据类型的基础上,包括数组、类和接口。那么为什么称之为引用类型,是因为引用数据类型的变量在内存中存储的是一个引用地址,这个地址指向真实数据的内存地址。那么我们来编写程序验证一下:

从图中我们可以看到数组类型数据array本身代表的是一个地址,那么我们思考一下为什么引用数据类型存储的是引用地址?它与基本数据类型存储的差别在哪里?
那么接下来我们就来简单了解一下Java程序在内存中的运行机制。

二、Java程序在内存中运行机制

首先我们知道Java程序在运行时,首先需要将编写的源代码(.java)编译(javac)为字节码文件(.class)之后,通过java执行工具在 jvm 执行,那么我们来看一下JVM的内存分布。

(一)、JVM内存组成

JVM可简单分为5大区域,分别是:方法区、堆、栈、本地方法区、程序计数器。其中主要了解 方法区、堆、 栈这三个区域。

1、方法区(Method Area)

方法区是被所有线程共享的内存区域,用来存储已被虚拟机加载的类信息、常量、静态变量、JIT(just in time,即时编译技术)编译后的代码等数据。运行时常量池是方法区的一部分,用于存放编译期间生成的各种字面常量和符号引用。

2、堆(Heap)

Heap存储着几乎所有的实例(new)对象,堆由垃圾收集器自动回收,堆区由各子线程共享使用;通常情况下,它占用的空间是所有内存区域中最大的,但如果无节制地创建大量对象,也容易消耗完所有的空间。

3、栈(Stack)

一般来说,基本数据类型直接在栈中分配空间,局部变量(在方法代码段中定义的变量)也在栈中直接分配空间,当局部变量所在方法执行完成之后该空间便立刻被JVM回收,还有一种是引用数据类型,即我们通常所说的需要用关键字new创建出来的对象所对应的引用(地址)也是在栈空间中。栈生命周期与线程相同。启动一个线程,程序调用函数,栈帧被压入栈中,函数调用结束,相应的是栈帧的出栈。

(二)、程序在JVM上运行

我们来写一个程序分析一下,代码如下:

public class StorageDemo {
    public static void main(String[] args) {
        /* 基本数据类型,变量中存储的是数据本身 */
        int a = 10;
        System.out.println(a);
        /*引用数据类型,变量中存储的是数据在内存中的地址*/
        int[] array = new int[]{11, 12, 13};
        System.out.println(array);
        /* 调用另一个方法 */
        Nesting(array);

    }
    public static void Nesting(int[] array) {
        System.out.println(array[1]);
    }

1、首先将 .class 文件加载到 jvm 的方法区中。然执行 main 方法,将该 main 方法中包含的变量和函数,压到栈中。

2、开始执行 main 方法中的指令,首先在栈中创建一个int型变量存储数据10,并输出。然后,创建一个数组对象array, 将 new 出来的数组对象array存储到堆中,array引用指向堆中的array对象,再根据array引用地址在堆中获取array对象对应的值,然后输出。

3、继续执行 main 方法中的指令,在栈中开辟新的空间执行Nesting()方法,根据传递的数组对象引用地址在堆中获取array对象对应的值,然后输出。如下图所示:
在这里插入图片描述

三、参数传递

在调用一个方法时,我们可能需要往方法中传递一些数据,称之为参数,参数分为实际参数(实参)和形式参数(形参),具体定义如下。前面我们已经知道Java数据类型分为基本数据类型和引用数据类型,那么在程序编写中,我们是如何传递这两类数据的呢?

形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数,简称“形参”。
实际参数:在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”,简称“实参”。

(一)、基本数据类型数据传递(值传递)

值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

根据定义,我们来写个程序验证一下:

public class StorageDemo {
    public static void main(String[] args) {
        /* 基本数据类型传输的是值本身 */
        int a = 33;

        DataTransmit(a);

        System.out.println(a);//执行方法后 33
    }
    public static void DataTransmit(int a) {

        System.out.println(a);//33

        a = 66;

        System.out.println(a);//66
    }
}

程序运行结果:
在这里插入图片描述
很容易得出结论:Java中,一个方法不会修改一个基本数据类型的参数。
注:当我们想获取修改后的数据时,只需要修改方法的返回值类型,并在方法中返回(return)受影响的数据。

(二)、引用数据类型数据传递(引用传递)

引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

根据定义,我们来写个程序验证一下

public static void main(String[] args) {
        /* 引用数据类型传输的是引用对象地址 */
        int[] array = new int[]{33, 66, 99};

        DataTransmit(array);

        System.out.println(array[2]);//执行方法后 88
    }
    public static void DataTransmit(int[] array) {

        System.out.println(array[2]);//99

        array[2] = 88;

        System.out.println(array[2]);//88
    }
}

运行结果如下:
在这里插入图片描述
其实,引用传递也可以称之为值传递,因为在main方法中的array中存储的是堆中array对象的地址的值。
注:当我们想传递一个对象而不影响其内的数据时,可以通过重写Object方法中的clone(方法来生成当前对象的一个副本,通过传递副本而不影响当前对象保存的数据。

如有错误,欢迎指正!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值