从零开始学习Java——基础知识之数组(第五天)
来源:互联网 发布:淘宝能贷款的口子 编辑:程序博客网 时间:2024/04/30 14:29
一、数组的定义
数组(Array)是一种数据存储结构,是一组相同类型的数据的集合,可以分为一维数组和多维数组,本篇文章主要是介绍一维数组。
1、数组的声明
数组使用前必须指定数组中存放数据的类型,也就是需要先声明;
格式为:
- 数据类型 [] 数组名;
- 数据类型 数组名 [];
第一种写法更符合Java的数据结构,所以推荐使用第一种书写方式;
int[] i;char[] c;double [] d;folat f [];//不推荐使用这种形式,一般是C语言的写法
2、数组的创建
- 数组名 = new 数据类型 [长度];
i = new int[10];c = new char[2];// new关键字是在内存开辟一块空间d = new double[32];// 指定数组的长度为32
**注意:**new关键字是在内存开辟一块空间
int[] ages = new int[48];
过程分析:首先在栈内存里存储ages变量,然后通过new关键字在堆内存中开辟一块32*48大小的空间,返回一个表示该块空间的地址(hashCode码)然后赋值给ages,最终ages里存储的是指向那块空间的地址(hashCode码)
- 当然声明和创建可以一起写:数据类型 [] 数组名 = new 数据类型 [长度];
int[] i = new int[10];
3、数组的初始化
在引用数组中的使用是通过:数组名 [下标] 的方式引用
(1)、静态初始化
直接在创建数组的时候就赋初值;
int[] ages = {12,13,32,42};// 推荐使用这种形式int ages[] = {12,13,32,42};int[] ages = new int[]{12,13,32,42};
注意:大括号中的内容必须为定义的数据类型,数组的长度会默认为大括号中的内容的长度。获取数组的长度“数组名.length”
(2)、动态初始化
int[] ages = new int[48];ages[0] = 21;ages[1] = 22;
动态的为数组中的每个值赋值。
4、数组的默认值
如果不给数组初始化,那么对应类型的数据类型数组会有相应的初始值;
/** @author sfbaobao 测试数组的初始值*/public class TestArrayDefaultValue{ public static void main(String[] args){ byte[] b = new byte[12]; short[] s = new short[12]; int[] i = new int[12]; long[] l = new long[12]; char[] c = new char[12]; float[] f = new float[12]; double[] d = new double[12]; boolean[] bool = new boolean[12]; System.out.println(b[0]);// 0 System.out.println(s[0]);// 0 System.out.println(i[0]);// 0 System.out.println(l[0]);// 0 System.out.println("-" + c[0] + "-");// - - 默认为空格 System.out.println(f[0]);// 0.0 System.out.println(d[0]);// 0.0 System.out.println(bool[0]);// false }}
- boolean类型的默认值为false;
- 整型类型的默认为 0;
- 小数类型的默认为 0.0;
- 字符类型的默认为 ‘\u0000’空格;
5、遍历数组
(1)、使用一般for循环遍历
public class Test{ public static void main(String[] args){ int [] nums = {1,2,3,4,5,6,7,8,9}; for(int i=0; i<nums.length; i++){ System.out.println(nums[i] + " "); } }}// out>>>1 2 3 4 5 6 7 8 9
通过nums.length
获取数组长度,再作为判断条件即可得到遍历数组中的每个元素。数组第一个元素下标是0即nums[0]为第一个元素。
注意:
数组下标越界异常:java.lang.ArrayIndexOutOfBoundsException
是在设计数组时容易出现的异常,需要检查程序中的数组下标是否超过了数组本身的长度或者为负数。
(2)、增强型for循环
for(数据类型 变量名 : 数组名){
功能代码;
}
int [] nums = {1,2,3,4,5,6,7,8,9};for(int n : nums){// 使用增强型for循环 System.out.println(n + " "); }}// out>>>1 2 3 4 5 6 7 8 9
在不考虑使用循环下标的情况下,使用增强型for循环会更方便
(3)、数组排序(调用Arrays的sort()):
Arrays.sort(数组名)升序
返回void类型即没有返回值
/** @author sfbaobao 测试Arrays.sort()数组排序方法*/import java.util.Arrays;public class TestArraySort{ public static void main(String[] args){ int[] nums = {1,22,13,231,34,45,23,25,45,3322,432}; Arrays.sort(nums);// 调用数组排序方法 for(int n : nums){ System.out.print(n + " "); } }}// out>>>1 13 22 23 25 34 45 45 231 432 3322
Arrays.sort(nums);
会将nums指向的内存空间存储的数据进行排序,虽然没有返回值,但是nums指向的内存空间的数据已经被排序了,所以输出nums指向的内存中存储的数据已经是拍好序的了。
二、通过数组赋值看看内存如何变化
在计算机内存中有两块存储空间,一个是栈内存,一个是堆内存;一般基本类型数据是存储在栈内存中,引用数据类型是存储在堆内存中。
假设有两个数组:
int[] a = {1,2,3,4,5};int[] b = a;// 画图内存图
当int[] b = a
语句执行时,b的值就等于a中存储的地址,所以b指向的空间也是a执行的那块内存。
int[] a = {1,2,3,4,5};int[] b = a;// 画图内存图a = {1,2,3,4,5};b = {1,2,3,4,5};
当执行’a = {1,2,3,4,5};’这条语句时,a首先会断开与堆内存1的联系,然后存储指向堆内存2的地址。此时堆内存1还有b指向它,所以堆内存1不会被Java垃圾回收机制回收。当执行完’b = {1,2,3,4,5};’时,b也断开了与堆内存1的联系,那这时堆内存1将变成垃圾,等待Java垃圾回收机制回收。
三、思考题
1、String类型数据存储在什么位置?
String s1 = new String("myString");// 第一种定义方式String s2 = "myString";// 第二种定义方式String s3 = "myString";
第一种方式通过关键字new定义过程:在程序编译期,编译程序先去字符串常量池检查,是否存在“myString”,如果不存在,则在常量池中开辟一个内存空间存放“myString”;如果存在的话,则不用重新开辟空间,保证常量池中只有一个“myString”常量,节省内存空间。然后在内存堆中开辟一块空间存放new出来的String实例,在栈中开辟一块空间,命名为“s1”,存放的值为堆中String实例的内存地址,这个过程就是将引用s1指向new出来的String实例。
第二种方式直接定义过程:在程序编译期,编译程序先去字符串常量池检查,是否存在“myString”,如果不存在,则在常量池中开辟一个内存空间存放“myString”;如果存在的话,则不用重新开辟空间。然后在栈中开辟一块空间,命名为“s1”,存放的值为常量池中“myString”的内存地址。
常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。常量池还具备动态性,运行期间可以将新的常量放入池中,String类的intern()方法是这一特性的典型应用。不懂吗?后面会介绍intern方法的。虚拟机为每个被装载的类型维护一个常量池,池中为该类型所用常量的一个有序集合,包括直接常量(string、integer和float常量)和对其他类型、字段和方法的符号引用(与对象引用的区别?读者可以自己去了解)。
/** 测试String类型数据的存储位置*/public class TestString{ public static void main(String[] args){ String s1 = new String("myString"); String s2 = "myString"; String s3 = "myString"; System.out.println(s1 == s2);// false System.out.println(s2 == s3);// true }}// out>>>false; true
本段解析摘自:java内存分配和String类型的深度解析
>>“不将就·能创新·耐得住——网络人”
- 从零开始学习Java——基础知识之数组(第五天)
- 从零开始学习Java——基础知识之了解Java(第一天)
- 从零开始学习Java——基础知识之流程控制(第三天)
- Java基础学习第五天——方法与数组
- Java学习第五天及基础知识回顾
- java学习总结——第五天
- 从零开始学习Java——基础知识之运算符(第二天)
- 从零开始学习Java——基础知识之循环语句练习题(第四天)
- Java学习之路(第五天)
- 学习JAVA第五天
- Java学习第五天
- JAVA 学习第五天
- 学习JAVA第五天
- JAVA学习第五天
- java学习第五天
- java学习第五天
- JAVA学习第五天
- JAVA学习第五天
- 图像傅立叶变换的物理意义
- SpringMVC学习
- android 学习笔记13-新特性Fragment 帧动画 补间动画 属性动画
- 编码与解码(python 经验)
- HTML5客户端数据存储Web Storage——localStorage与sessionStorage
- 从零开始学习Java——基础知识之数组(第五天)
- kruscal最小树
- 初学linux(-)
- ftp服务
- Oracle学习之:数据迁移工具(1):SQL Loader
- 千古
- 初学linux(二)
- 工程管理器——make
- 江湖