1、数组是一种引用类型的变量
1、java中的数组是用于存放一系列相同类型数组的(即可以存放基本数组类型,也可以存放引用用类型,只要类型相同就可以)
2、数组初始化后,在内存中的大小已经确定,长度不可以改变,即使把数组中的数据移除,数组的大小,仍然不会改变,在内存中的大小依旧不变。
3、数组的初始化是指为数组分配内存空间,并这每个元素赋初始值。比如int数组默认0,引用类型String(默认值null)。注:String类型基本数据类型,只是一个java类(和8种数组类型有本质区别)
8种基本数据类型
整型:byte,short,int,long
浮点型:float,double
字符型:char
布尔型:boolean
引用类型:类,接口,数组
2、数组与内存
1、数组是一种引用数据类型,数组元素和数组变量在内存是分开存放的。访问数组中的元素时,我们只能通过数组的引用变量来访问数组中的真实元素。
2、数组的引用存放在栈中,数组的真实对象存放在堆中
注:堆栈内存之分
java中对于一些变量的使用情况不同,存放不同的地方,一些经常使用,而一些不容易创建,甚至不知道何时销毁,因此有了堆栈内存之分(这样设计的目的是为了充分自用内存,提高性能)
栈内存:在方法中定义的局部变量都保存在栈中。保存在栈中,随着方法的结束而结束,内存栈也就销毁
堆内存:存放我们的成员变量,数组,和new出来的对象,存放在堆中,不会随着类或者方法的结束而销毁,只有当没有任何引用的时候,可能 被GC回收。
3、数组的初始化
public class MyClass4 {
public static void main(String[] args) {
int a[] ; //定义一个数组,此时,在栈中新建一个a的引用
a=new int[5];//初始化,分配内存空间,在堆中开辟地址,并带有默认值
a[1]=2;//把下标了1的默认值用当前值覆盖
}
}
1、int a[]内存分析:在栈中建立数组引用
2、当执行到a =new int[5]的时候,开辟堆内存,默认值
3、当赋值操作的时候
4、数组长度不可变分析
示例:
public class MyClass3 {
public static void main(String[] args) {
int a[]={1,2,3};
int b[] =new int[4];
System.out.println("a.length--"+a.length);
System.out.println("b.length--"+b.length);
//把a赋值给b
b=a;
System.out.println("b.length--"+b.length);
}
运行结果:
可以看出在运行前a的长度是3,b的长度是4,赋值后,b的长度是3。数组的长度可变吗?数组的长度是不可改变的,改变的只是它的引用。
在赋值前的堆栈内存
赋值后的堆栈内存
5、实现数组扩容
1、数组的长度不可变,但在实际需求中,我们没有办法知道一开始的数组长度,也不知道何时添加,删除元素,以此数组扩容很有必要。
2、但是,要始终记得,数组长度不可变,不管添加还是移除的元素,都是一个新的数组,与原来的数组没有关系。
package com.example;
public class MyClass3 {
static int[] a = {1, 2, 3};
public static void main(String[] args) {
int[] c = {7, 9,0};
addNum(2);
addList(c);
myPrint();
deleteNum(5);
myPrint();
}
//通过下标移除当前元素
private static void deleteNum(int n) {
if(n<0&&n>a.length){
return;
}
int[] b=new int[a.length-1];
for(int i=0;i<a.length-1;i++){
if(i<n) {
b[i] = a[i];
}else{
b[i]=a[i+1];
}
}
a=b;
}
//把一个集合添加到另一个集合中
private static void addList(int[] c) {
int[] b =new int[a.length+c.length];
for (int i = 0; i < b.length; i++) {
if(i<a.length){
b[i]=a[i];
}else{
b[i]=c[i-a.length];
}
}
a=b;
}
//打印
private static void myPrint() {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
System.out.println("a.length-->"+a.length);
}
//添加一个数字到集合中
private static void addNum(int num) {
int[] b = new int[a.length + 1];
for (int i = 0; i < b.length; i++) {
if (i < a.length) {
b[i] = a[i];
} else {
b[i] = num;
}
}
a = b;
}
}
上面addNum()方法,向数组中添加一个元素,就是重新创建一个长度加1的数组,把这个元素放入数组中
addList()方法,向数组中添加一个数组,也是重新创建一个新的数组,然后把要添加的元素添加到新集合后面。
deleteNum()方法,通过下标删除当前元素,其实是把后面的元素向前赋值,空出一个元素后,把当前数组长度减1
上面的代码,只是一个demo,在实际开发中,但在实际开发中我们真的需要这种变长数组,java中其实已经帮我们做了好,那就是ArrayList集合,ArrayList其实是封装的数组,简化我们操作数组,比如给集合中添加元素,删除元素。这其实都是对数组的操作,添加元素,就要产生新的数组,把旧的数组copy进入,然后把想要添加的追加到后来。
数组所拥有的属性ArrayList也就有,
ArrayList扩容机制分析
http://blog.csdn.net/androidxiaogang/article/details/52281217