java中数组的定义与使用说明,Java中数组的定义

java中数组的定义与使用说明,Java中数组的定义,Java中数组的定义与使用

下面简单介绍一下java中数组的定义和使用。我觉得挺好的。我现在就分享给你,给你一个参考。来和边肖一起看看吧。

:

目录

1.数组1的基本用法。什么是数组2。创建数组3。使用数组2。数据作为方法参数1。基本用法2。了解参考类型3。知否null 4。划分JVM内存区域5。数组作为方法6的返回值。数组4的地址。阵列练习1。数组转换为字符串2。数组副本5。二维数组1。二维数组的语法2。

一、数组的基本用法

1.什么是数组

数组本质上允许我们“批量”创建相同类型的变量。

如果我们需要创建多个同类型的变量,不可能手工逐个创建,比如:int n=10int m=20int y=30等等,所以数组可以帮助我们批量创建相同类型的数据。

注意:在Java中,数组中包含的变量必须是同一类型。

2.创建数组

基本语法:

//动态初始化

数据类型数组名[]=新数据类型[]{初始化数据};

//静态初始化

Type []数据数组名称={初始化数据};

//不要初始化

Type [] array name=新数据类型[要创建的数组长度];

代码示例:

int[] arr=new int[]{1,2,3 };

int[] arr={1,2,3 };

int[]arr=new int[3];

注意:静态初始化时,数组元素的个数与初始化数据的格式一致。

虽然我们也可以用:int arr[]={1,2,3 };但还是更推荐用int[] arr的形式来写。Int和[]是一个整体。

3.数组的使用

int[] arr={1,2,3 };

//获取数组长度

system . out . println(' length:' arr . length ');//执行结果:3

//访问数组中的元素

system . out . println(arr[1]);//执行结果:2

system . out . println(arr[0]);//执行结果:1

arr[2]=100;

system . out . println(arr[2]);//执行结果:100

1.数组的长度可以通过使用arr.length获得,这个操作是一个成员访问操作符。在面向对象的后面会经常用到。

2.使用[]通过下标提取数组元素。需要注意的是下标从0开始计数。

3.使用[]操作不仅可以读取数据,还可以修改数据。

4.下标访问操作不能超出有效范围[0,长度-1]。如果是这样,将发生下标越界异常。

代码示例: 下标越界

int[] arr={1,2,3 };

system . out . println(arr[100]);

//执行结果

线程“main”Java . lang . arrayindexoutofboundsexception中的异常:Test.main处的100(test . Java:4)

引发了Java . lang . arrayindexoutofboundsexception异常。使用数组时,必须给它加下标以防止越界。

代码示例:遍历数组

所谓“遍历”是指将数组中的所有元素访问一次,不遗漏任何东西,通常使用循环语句。

int[] arr={1,2,3 };for(int I=0;长度;I){ system . out . println(arr[I]);

}

//执行结果

一个

2

代码示例: 使用 for-each 遍历数组

int[] arr={1,2,3 };

for (int x : arr) {

system . out . println(x);

}

//执行结果

一个

2

For-each是For循环的另一种使用方式,可以更方便地完成数组的遍历,避免循环条件和update语句的错误写入。

另一种方式使用for-each,它只能遍历数组中的所有数据,X可以在遍历时读取数组中对应下标的数据。

代码示例:

int[] arr={1,2,3,4,2 };

int count=0;

for (int x:arr) {

if(x==2) {

数数;

}

}

system . out . println(count);//结果是2

二、数据作为方法参数

1.基本用法

代码示例: 打印数组内容

公共静态void main(String[] args) {

int[] arr={1,2,3 };

打印数组(arr);

}

public static void print array(int[]a){

for (int x : a) {

system . out . println(x);

}

}

//执行结果

一个

2

注意:

1.int[] a是函数的形参,int[] arr是函数的实参。

2.如果需要获得数组长度,也可以使用. length

2.理解引用类型

代码示例1 参数传内置类型

公共静态void main(String[] args) {

int num=0;

func(数字);

system . out . println(' num=' num);

}

公共静态void函数(int x) {

x=10

system . out . println(' x=' x);

}

//执行结果

x=10

数量=0

代码示例2 参数传数组类型

公共静态void main(String[] args) {

int[] arr={1,2,3 };

func(arr);

system . out . println(' arr[0]=' arr[0]);

}

public static void func(int[] a) {

a[0]=10;

system . out . println(' a[0]=' a[0]);

}

//执行结果

a[0]=10

arr[0]=10

我们发现在方法内部修改数组的内容也会改变方法的外部。

这时数组名arr就是一个“引用”。传递参数时,参数是根据引用传递的。引用类型类似于C语言中的指针,但有许多不同之处。

引用可以理解为:创建一个引用就相当于创建了一个很小的变量,这个变量保存了一个表示内存中地址的整数。

对于int[] arr=new int[]{1,2,3}这样的代码,内存布局如下:

当我们创建new int[]{1,2,3}时,相当于创建了一个内存空间来存放三个int。接下来,执行int[] arr=new int[]{1,2,3}相当于创建另一个int[]变量,这个变量是一个引用类型,只保存一个整数(数组的起始内存地址)。

3.接下来传递参数等价于int[] a=arr,内存布局如图所示:

4. 接下来我们修改 a[0] , 此时是根据 0x100 这样的地址找到对应的内存位置, 将值改成 100 。内存布局如图:

因为创建arr时int[] arr和int[] a所指向的内存空间都是新对象(三个整数数据),虽然其中一个数据发生了变化,但是arr和a所指向的空间保持不变,所以arr和a都会随着对象的变化而变化,这就是引用。

总结: 所谓的“引用”本质上只是存储一个地址,Java将数组设置为引用类型。在这种情况下,数组的后续参数传递实际上只是将数组的地址传入函数参数,可以避免复制整个数组(数组可能会更长,所以复制开销会很高)

3.认识null

Null在Java中是“空引用”的意思,是无效引用。

代码示例:

int[]arr=null;

system . out . println(arr[0]);

//执行结果

线程“main”中的异常Java . lang . nullpointerexception at test . main(test . Java:6)

null的作用类似于C语言中的NULL(空指针),表示无效的内存位置。因此,你不能读写这个内存。一旦尝试读写,就会抛出NullPointerException。

注意:Java中没有约定null和地址0的内存有什么关系。即使打印出来,打印出来的结果也是null。

4.JVM内存区域划分

学习Java之初,我们知道JVM的全称是Java虚拟机,可以运行Java编译的字节码文件。实际上运行时,它要打开堆栈帧,在堆中分配内存等等,于是就有了JVM的内存布局。

JVM的内存布局可以分为六个区域:程序计数器、JVM虚拟机栈、JVM本地方法栈、方法区、堆区和运行时常量池。它们之间的内存布局:

程序计数器(PC寄存器):它只是一个小空间,用来保存下一条执行指令的地址。

虚拟机栈:重点是存储局部变量表(当然还有其他信息)。我们刚刚创建的int[] arr之类的存储地址的引用保存在这里。

Native Method Stack:native Method Stack的功能和虚拟机Stack类似,只是存储的内容是native Method的局部变量,运行速度非常快。在某些版本的JVM实现中(比如HotSpot),本机方法栈和虚拟机栈是在一起的。

堆:JVM管理的最大内存区域。用new创建的所有对象都保存在堆上(例如,前面的new int[]{1,2,3})

方法区(Method Area):用于存储已经被虚拟机加载的类信息、常量、静态变量、实时编译器编译的代码等数据。由方法编译的字节存储在这个区域。

运行时常量池:方法区的一部分,存储文字量(字符串常量)和符号引用(注意从JDK1.7开始,运行时常量池在堆上)。

本机方法:

JVM是基于C的程序,在Java程序执行过程中,调用C提供的一些函数与操作系统底层进行交互是必不可少的。所以C实现的一些功能在Java开发中会被调用。

这里的原生方法指的是这些由C实现,然后由Java调用的函数。

这里我们只知道JVM的内存布局,重点是JVM虚拟机栈中存储了什么,栈上存储了多少。

局部变量和引用存储在堆栈上,新对象存储在堆上。

堆空间很大,栈空间相对较小。

堆栈由整个JVM共享,每个线程有一个堆栈(一个Java程序中可能有多个堆栈)。

5.数组作为方法的返回值

代码示例:编写一个方法使数组中的每个元素* 2

//直接修改原数组

类别测试{

公共静态void main(String[] args) {

int[] arr={1,2,3 };

transform(arr);

打印数组(arr);

}

public static void print array(int[]arr){

for(int I=0;长度;i ) {

system . out . println(arr[I]);

}

}

公共静态void转换(int[] arr) {

for(int I=0;长度;i ) {

arr[I]=arr[I]* 2;

}

}

}

这段代码是可行的,但是它破坏了原始数组。有时候我们不想破坏原来的数组,就需要在方法内部创建一个新的数组,由方法返回。在Java中,一个方法可以返回一个数组。

//返回新的数组类Test {

公共静态void main(String[] args) {

int[] arr={1,2,3 };

int[]output=transform(arr);

printArray(输出);

}

public static void print array(int[]arr){

for(int I=0;长度;i ) {

system . out . println(arr[I]);

}

}

公共静态int[] transform(int[] arr) {

int[]ret=new int[arr . length];

for(int I=0;长度;i ) {

ret[I]=arr[I]* 2;

}

返回ret

}

}

这样,原来的阵列就不会被破坏。

另外,由于数组是引用类型,所以返回时只将数组的第一个地址返回给函数调用方,不复制数组的内容,所以效率更高。

6.关于数组的地址

在Java中,为了维护数据的安全性,我们不能获取数组的地址(已经做了特殊处理)。如果你想打印数组的地址,我们会发现下面的结果:

为什么打印结果是这样的?

进入println的源代码,可以看到println中有一个专门处理地址的方法:

它根据哈希值处理数组的地址,但数组的地址仍然是唯一的。

四、数组练习

1.数组转字符串

代码示例:

导入java.util.Arrays

int[] arr={1,2,3,4,5,6 };

string new arr=arrays . tostring(arr);

system . out . println(new arr);

//执行结果

[1, 2, 3, 4, 5, 6]

以后用这种方法打印数组更方便。

Java提供了java.util.Arrays包,其中包含了一些操作数组的常用方法。

2.数组拷贝

代码示例:

导入java.util.Arrays

int[] arr={1,2,3,4,5,6 };

int[] newArr=Arrays.copyOf(arr,arr . length);

system . out . println(' newArr:' arrays . tostring(newArr));

arr[0]=10;

system . out . println(' arr:' arrays . tostring(arr));system . out . println(' newArr:' arrays . tostring(newArr));

//复制一个范围。

int[]new arr=arrays . copyofrage(arr,2,4);

system . out . println(' new arr 2:' arrays . tostring(new arr 2));

注意:与newArr=arr的赋值相比,copyOf是对数组进行深度复制,即创建另一个数组对象,将原数组中的所有元素复制到新数组中。因此,修改原始数组不会影响新数组。而轻拷贝是拷贝时原始阵列。

实际上,复制数组有四种方法。

1.for循环逐个复制。

2.调用Arrays包中的类来实现它。

3.System.arraycopy,它可以设置复制开始和结束的位置(最快的复制)

4.数组名。克隆()

虽然这四种复制数组的方法都有深度复制的特点(复制到一个新的数组中,改变新数组中的数据,原数组不会改变)。不过都是处理简单类型的,面试的时候都可以作为浅抄来回答。

代码示例:

for循环拷贝:

int[] arr={1,2,3,4 };

int[]a=new int[4];

for(int I=0;iarr .长度;i ) {

a[I]=arr[I];

}

for (int x:a) {

system . out . println(x);

}

System.arraycopy拷贝:

int[] arr={1,2,3,4 };

int[]a=new int[arr . length];

System.arraycopy(arr,0,a,0,arr . length);

system . out . println(arrays . tostring(a));

数组名.clone拷贝:

int[] arr={1,2,3,4 };

int[]a=new int[arr . length];

a=arr . clone();

system . out . println(arrays . tostring(a));

五、二维数组

1.二维数组的语法

二维数组本质上是一维数组,只是每个元素都是一维数组。

基本语法:

数据类型数组名[] []=新数据类型[行数] [列数]{初始化数据};

代码示例:

int[][] arr={ {1,2,3,4},{5,6,7,8},{9,10,11,12 } };

for(int row=0;行排列长度;row ) {

for(int col=0;列排列[行]。长度;col ) {

System.out.printf('%d\t ',arr[row][col]);

}

system . out . println(');

}

//执行结果

1 2 3

4 5 6

7 8 9

10 11 12

注意:Java中的二维数组只能省略列,不能省略行,否则编译器会报错。

二维数组可以定制,那么怎么定制呢?

代码示例:

int[][]arr=new int[2][];

arr[0]=new int[]{1,2,3 };

arr[1]=new int[]{4,5 };

for (int[] a:arr) {

for (int x:a) {

system . out . print(x ' ');

}

system . out . println();

}

运行结果:

2.二维数组的结构

这里我们分析一下数组int[2][3]的结构。类似地,当创建新的二维数组对象时,它们被存储在堆区中,而数组名(变量)是引用并存储在堆区中。

注意:在Java中,要获取二维数组的行号,实际上是一维数组,所以上面打印二维数组的代码中获取行号的方式是arr.length,是一维数组,所以获取二维数组每一列的方式是arr[row]。长度

3.用for-each遍历二维数组

使用foreach遍历二维数组:

代码示例:

int[][] arr={{1,2,3},{2,3,4 } };

for (int[] tmp:arr) {

for (int x:tmp) {

system . out . print(x ' ');

}

system . out . println();

}

总结

本文到此为止。希望能帮到你,也希望你能多关注我们的更多内容!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: