重学java-5.数组的基本概念

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/euzmin/article/details/88558594

数组的基本概念

在java中,数组属于引用型数据,指的是一组相关便令的集合。

一维数组

三种定义方式

public static void main(String[] args) {
		//1
		int [] array1 = new int[100];
		//2
		int array2[] = new int[100];
		//3
		int array3[] = null;
		array3 = new int[100];
}

这三种方法中,1和2只是写法上的不同。但3与1和2在内存的申请上有所不同。

  • 1和2在申请内存时,把array1,array2存放在栈中的同时,在堆中申请相应的内存,并让array1和array2指向堆中信息。
  • 3分为两步,第一步是把array3存放在栈中,在第二步执行以前,array3都指向null。直到第二部执行,array3才指向堆。

两种初始化

  • 静态初始化:数组在申请空间的同时就设置好了相应的数据内容。
  • 动态初始化:数组在申请空间后添加数组内容。

下面举个小例子:

public static void main(String[] args) {
		//动态初始化
		int [] array1 = new int[3];
		array1[0] = 1;
		array1[1] = 2;
		array1[2] = 3;
		
		System.out.print("array1: ");
		for(int i = 0; i < array1.length; ++i) {
			System.out.print(array1[i] + " ");
		}
		System.out.println();
		
		//静态初始化
		int array2[] = new int[] {4,5,6};
		
		System.out.print("array2: ");
		for(int i = 0; i < array2.length; ++i) {
			System.out.print(array2[i] + " ");
		}
		System.out.println();
		
	}

运行结果:
在这里插入图片描述

二维数组

二维数组的定义与初始化与一维的大同小异,在这里举个简单的例子:

public static void main(String[] args) {
		//1
		int array1[][] = new int[2][2];
		//2 静态初始化
		int [] array2[] = new int[][] {{1,2},{3,4}};
		//3 动态初始化
		int array3[][] = null;
		array3 = new int[2][2];
		
		int cnt = 0;
		for(int i = 0; i < array3.length; ++i) {
			for(int j = 0; j < array3[i].length; ++j) {
				array3[i][j] = ++cnt;
			}
		}
		
		//输出
		System.out.print("array2: ");
		for(int i = 0; i < array2.length; ++i) {
			for(int j = 0; j < array2[i].length; ++j) {
				System.out.print(array2[i][j]+ " ");
			}
		}
		System.out.print('\n'+"array3: ");
		for(int i = 0; i < array3.length; ++i) {
			for(int j = 0; j < array3[i].length; ++j) {
				System.out.print(array3[i][j]+" ");
			}
		}
	}

运行结果:
在这里插入图片描述

数组的引用传递

根据 重学java-4.面对对象基本概念 可知,引用数据类型都可以进行引用传递操作,因此数组也可以进行引用传递操作。
举个例子:

public static void main(String[] args) {
		
		int [] array1 = new int[] {1,2,3};
		int array2[] = array1;//引用传递,使array2指向array1所指向的堆
		
		array2[0] = 4;//通过array2改变堆内的值
		
		System.out.println("array1: ");
		for(int i = 0; i < array1.length; ++i) {
			System.out.print(array1[i] + " ");
		}
	}

运行结果:
在这里插入图片描述

方法参数的传递

标题很长,其实就是想讨论一下数组、类等引用数据类型作为一个方法的参数是如何存在的,便于我们加深对栈内存与堆内存的理解。

基本数据类型作为方法的参数

public class test1 {
   public static void main(String[] args) {
   	int a = 1;
   	change(a);
   	System.out.println(a);
   }
   public static void change(int b) {
   	b = 2;
   }
}

运行结果:
在这里插入图片描述
我们发现a的值在传入change方法后明明更改为2,但最终输出时却仍是1。暂且不提为什么,我们继续往下看。

引用数据类型作为方法的参数

  • 数组
public class test1 {
   public static void main(String[] args) {
   	int arraya[] = new int[] {1,2};
   	change(arraya);
   	System.out.println(arraya[0]);
   }
   public static void change(int[] arrayb) {
   	arrayb[0] = 3;
   }
}

运行结果:
在这里插入图片描述
更改成功。

public class test1 {
   public static void main(String[] args) {
   	Book booka = new Book("野草");
   	fun(booka);
   	System.out.println(booka.getName());
   }
   public static void fun(Book bookb) {
   	bookb.setName("狂人");
   }
}

class Book {
   private String name;

   public Book(String name) {
   	super();
   	this.name = name;
   }

   public String getName() {
   	return name;
   }

   public void setName(String name) {
   	this.name = name;
   }
}

运行结果:
在这里插入图片描述
更改成功。
在上面的代码中,我们实例化了一个Book类型的对象booka,将booka作为参数传入了fun方法中,调用该方法。而在fun方法中,把Book类型的bookb的name属性更改为"狂人"。fun方法结束后,输出booka的name属性,发现其已然改为"狂人"。

以上两段代码,如果把方法这个载体省去,main函数的过程与Book bookb = booka,int[] arrayb = arraya的引用传递过程并无区别。事实上也正是如此,当我们把booka传入fun方法时,就是实现了bookb = booka的过程

变量传参后是否影响外界的值

在基本数据类型作为参数的时候,我们发现在方法中更改的数据又回归原值。这是数据类型的原因,还是方法的特性?
还是之前的例子,我加入了一个change方法,负责改变类的指向。

public class test1 {
	public static void main(String[] args) {
		Book a = new Book("野草");
		Book b = new Book("坟");
		fun(a);
		change(a, b);
		
		System.out.println(a.getName());
		System.out.println(b.getName());
	}
	public static void fun(Book bookb) {
		bookb.setName("狂人");
	}
	public static void change(Book a, Book b) {
		b = a;
	}
	public static void fun2(int b) {
		b = 2;
	}
}

class Book {
	private String name;

	public Book(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

运行结果:
在这里插入图片描述
可以发现,经过引用传递的值成功改变,而直接改变参数的值则无效。这与方法本身的特性有关,当我们调用一个方法,系统就会在栈中申请一段空间用来存储方法中的值,而这段空间的寿命会伴随着方法的结束而结束。

之所以使用引用传递能改变原来的值,是因为它改变的是参数所指向的值。这样说有点绕,我们可以举个例子:
定义一个方法,传进去的参数是一个门牌号。此时,系统会在栈中申请一段空间,并在这段空间中制作门牌号的副本。显然,无论怎么改变副本,都与原来的门牌号无关。但如果我们要改变门牌号对应的房子,那就一改一个准了,因为无论做了几个副本,只要牌号正确,我们都能按照门牌号找到房子。其实这就是c++中指针的工作机制。

猜你喜欢

转载自blog.csdn.net/euzmin/article/details/88558594