下面我带你们一块儿加深一下对Java数组的认识:java
1.理解数组express
数组也是一种数据类型,自己就是一种引用类型,咱们从它的初始化方法,经过关键字new去完成定义及初始化就能够知道。数组
数组的长度是不变的,一旦数组完成初始化后,它的长度就固定下来了,在内存中占有的空间也就固定了,即便里面的数据被清空了,占有的空间仍是保留下来了,依然是属于数组的,固然长度依旧是不变的。ide
数组里边存放的数据类型要一致,能够基本数据类型,也能够是引用数据类型,可是惟一的标准就是相同的类型。在Java中,类与类是支持继承关系的,因此就可能形成数组里面能够存在多中数据类型的假象:工具
示例:this
class Animal { public String name; public Animal(String name) { this.name = name; } } class Cat extends Animal { public Cat(String name) { super(name); } } class Dog extends Animal { public Dog(String name) { super(name); } } public class ArrayDemo { public static void main(String[] args) { Animal[] animals = new Animal[2]; Cat cat = new Cat("little cat"); Dog dog = new Dog("little dog"); animals[0] = cat; animals[1] = dog; System.out.println(animals[0].name); System.out.println(animals[1].name); } }
这样看上去,好像数组里面存放了Cat类型和Dog类型,可是实际上他们都是Animal类型,数组里面都是相同的类型,请你们不要搞混淆了,哈哈。spa
2.定义数组和初始化数组code
定义数组的语法格式:对象
type[] arrayName;
type arrayName[];
这两种格式,我是强烈推荐第一种的,第一种格式给人很是的明确,定义了一个变量,它是type数组类型,可是第二种就可能给人一种假象,定义了一种变量,它是type类型的,为了避免给别人误会,仍是选择第一种好点咯。
定义完了数组,这是内存中还没给数组分配空间,真正分配内存空间的时候就是在给数组初始化的时候。blog
初始化数组分两种:
静态初始化:
arrayName = new type[]{element1,element2, element3......};
由上面很容易看出静态的初始化就是显式指定数组每一个元素的初始值,由系统决定数组的长度。
动态初始化:
arrayName = new type[length];
由上面看出动态初始化就是只指定数组的长度,由系统为数组分配初始值。
对于不一样类型,系统分配的初始值也是不同的。
类型 |
初始值 |
整数类型(byte、short、int、long) |
0 |
浮点类型(float、double) |
0.0 |
字符类型(char) |
'\u0000'(表明空格) |
布尔类型(boolean) |
false |
引用类型(类、接口、数组) |
null |
你可能产生这样的猜测:不是能够同时使用静态初始化和动态初始化吗?
答案是不能够的,编译器是提示Cannot define dimension expressions when an array initializer is provided,由于你定义了长度,说明你已经初始化完了,我想一想也是以为这样不合理的,若是能够二者混合使用的话,那么我定义好了数组的长度后,系统是否是要给它附上默认的初始值,可是你后面又是静态的初始化,指定了特定的值,系统又要为你改变里面的值,这样作系统真累,我也以为累。固然编译器是不支持二者混合使用的,你们注意了!
3.数组的使用
数组的使用就是引用数组的索引,数组的索引是从0开始的,到length-1为止,若是超过了这样范围就是抛出java.lang.ArrayIndexOutOfBoundException异常,就是数组索引越界异常,引用数组的使用太简单了,下面就简单用for和foreach来演示一下访问:
public class ArrayDemo2 { public static void main(String[] args) { String[] strings = new String[]{"hello", "world"}; for(int i = 0; i < strings.length; i++) System.out.println(strings[i]); for(String string : strings) System.out.println(string); } }
4.内存中的数组:
type[] arrayName = new type[]{element1, element2, element3......};
arrayName就是一个引用的变量,这个数组的引用变量能够指向任何有效的内存,只有当指向有效的内存后才能够方位数组元素,能够这么说,引用变量是访问真是对象的根本方式。
实际的数组对象被存储在堆(heap)内存中,若是引用该数组独享的数组引用变量是一个局部变量的话,那么它被存储在栈(stack)内存中,示意图以下:
由这里咱们能够很清楚的看出局部数组引用变量是怎么访问到内存中的数组的,党当一个方法调用完后,局部变量就没了,也就是从栈内存中消失了,若是堆内存中数组再也不有任何引用变量指向本身,这个数组将成为垃圾,该数组所占的内存就会被系统的垃圾回收机制回收,所以,为了让垃圾回收机制回收一个数组所占的内存空间,能够将数组变量赋值为null,也就切断了数组引用变量和实际数组之间的关系,实际的数组也就成为了垃圾。
在这里,咱们让一个引用变量指向另一个实际的数组的时候,可能产生数组长度可变的假象,你们来看看一个例子:
public class ArrayDemo3 { public static void main(String[] args) { int[] a = new int[]{1, 2}; int[] b = new int[4]; System.out.println("length of b:" + b.length); b = a; System.out.println("length of b:" + b.length); } }
结果:
length of b:4
length of b:2
从上面看咱们b数组的长度好像发生了变化,可是实际上不是这样的,咱们来分析一下内存中的变化:
先是这样:
而后这样:
咱们所说的数组的长度不变是针对堆内存中真正数组的长度,引用变量是能够改变指向的,指到哪里确定就显示指到的数组的长度了,可是真正的长度是未曾改变的。
5.操做数组的工具类:
Java提供的Arrays类里包含的一些static修饰的方法能够直接操做数组
int binarySearch(type[] a, type key):使用二分法查询key元素值在a数组中出现的索引,若是a数组不包含key元素值,就返回负数,调用该方法的前提是数组中的元素已经按照升序排列好了。
type[] copyOf(type[] original, int newLength):这个方法能够将original数组复制到一个新的数组,这个新的数组的长度为newLength。
boolean equals(type[] a, type[] b):若是a数组和b数组的长度相等,并且数组中的元素一一相等,该方法就返回true。
void fill(type[] a, type val):该方法会将数组中的所有元素赋值为val。
void sort(type[] a):该方法对a数组进行(升序)排序。