源码可以做网站吗,信息网站建设的意义,千灯网站建设,网站开发算固定资产目录
1. 数组的概念
2. 数组的基础知识
2.1 数组的创建
\1. 基础创建格式#xff1a;
\2. 类似C语言的创建格式#xff1a;
【错误的创建(初始化)格式】
2.2 数组的数据类型
2.3 数组的初始化 —— 两种方式
\1.动态初始化#xff1a;(完全默认初始化)
\2. 静态初…目录
1. 数组的概念
2. 数组的基础知识
2.1 数组的创建
\1. 基础创建格式
\2. 类似C语言的创建格式
【错误的创建(初始化)格式】
2.2 数组的数据类型
2.3 数组的初始化 —— 两种方式
\1.动态初始化(完全默认初始化)
\2. 静态初始化
【注意事项】
3. 数组的使用
3.1 数组元素的下标访问
3.2 计算数组长度
3.3 循环遍历数组的2种方式
\1. for语句
\2. for - each语句
【两种遍历方式的区别】
4. 数组是引用类型内存空间的底层知识
4.1 JVM的内存区域划分
4.2 内存分配基础类型的变量 和 引用类型的变量
4.3 数组大小可变吗
4.4 “数组1 数组2”会发生什么
4.5 空引用null
5. 数组 与 方法
5.1 数组作为方法参数
5.2 数组作为方法返回类型
6. Arrays的一些实用工具方法
6.1 数组转字符串
6.2 数组的拷贝
6.3 数组的排序
6.4 二分查找指定元素
6.5 判断两个数组是否相等
6.6 填充数组元素 1. 数组的概念 数组可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。 1. 数组中存放的元素其类型相同。
2. 数组的空间是连在一起的。
3. 每个空间有自己的编号起始位置的编号为0即数组的下标。 2. 数组的基础知识 首先要明确一点数组在Java中属于引用类型引用类型变量的创建都需要new出来。 2.1 数组的创建 \1. 基础创建格式 T[ ] 数组名 new T[N]; T表示数组中存放元素的类型T[ ]表示数组的类型N表示数组的长度 例如
int[] array1 new int[10]; // 创建一个可以容纳10个int类型元素的数组double[] array2 new double[5]; // 创建一个可以容纳5个double类型元素的数组String[] array3 new String[3]; // 创建一个可以容纳3个字符串元素的数组 数组的创建也可以类似C语言那样把方括号[]写在变量名的右边。 \2. 类似C语言的创建格式 T 数组名[ ] new T[N]; T表示数组中存放元素的类型T[ ]表示数组的类型N表示数组的长度 例如
int array1[] new int[10]; // 创建一个可以容纳10个int类型元素的数组double array2[] new double[5]; // 创建一个可以容纳5个double类型元素的数组String array3[] new String[3]; // 创建一个可以容纳3个字符串元素的数组 【错误的创建(初始化)格式】 没有new一个数组对象。将数组长度的定义写在了第一个方括号[ ]里面。 例如 2.2 数组的数据类型 注意java中数组的数据类型是T[]而不是T[n]。 【在C语言中数组的数据类型是T[n]】 比如现在有1个元素个数为3的整型数组“int[] arr new int[3]”那么该数组arr的数据类型是int[ ]而不是int[3]。 2.3 数组的初始化 —— 两种方式
数组的初始化主要分为动态初始化以及静态初始化。 \1.动态初始化(完全默认初始化) 在创建数组时直接指定数组中元素的个数N。创建后从0到N-1的数组元素都被默认初始化。 语法格式T[ ] 数组名 new T[N]; 例如int[] array new int[10]; 如果数组中存储元素类型为基础类型默认值为基础数据类型对应的默认值比如 \u 是用来表示Unicode转义字符的前缀。它的格式为 \u 后面跟着四个十六进制数字用于表示一个特定的Unicode字符。 例如\u0041 表示字符 A因为 0041 是 A 的Unicode编码。 如果数组中存储元素类型为引用类型默认值为null \2. 静态初始化 在创建数组时不直接指定数据元素个数而直接将具体的数据内容进行指定。 (完全格式)语法格式①T[ ] 数组名 new T[ ]{data1, data2, data3, ..., datan}; (左边也可以写成“T 数组名[ ]”) (省略格式)语法格式②T[ ] 数组名 {data1, data2, data3, ..., datan}; (左边也可以写成“T 数组名[ ]”) 【这写法类似C语言的数组完全初始化虽然看上去省去了new T[ ]但是编译器编译代码时还是会还原】 例如
格式1的静态初始化
int[] array1 new int[]{0,1,2,3,4,5,6,7,8,9};String[] array3 new String[]{hell, Java, !!!};
格式2的静态初始化
int[] array1 {0,1,2,3,4,5,6,7,8,9};double[] array2 {1.0, 2.0, 3.0, 4.0, 5.0};String[] array3 {hell, Java, !!!}; 【注意事项】 1.静态和动态初始化也可以分为两步但是省略格式不可以。【类似C语言的初始化格式不能分成两步而且这在C语言中也是不可以的】 int[] array1;array1 new int[10];int[] array2;array2 new int[]{10, 20, 30};// 注意省略格式不可以拆分, 否则编译失败
// int[] array3;// array3 {1, 2, 3}; 2. 在使用省略格式的静态初始化时浮点数数组不能用float[ ]类型接收整数无限制。所以不太建议使用省略格式 3. 数组的初始化不能既是动态初始化又是静态初始化。(同时也说明Java中不能像C语言那样不完全初始化。) 这里既直接指定了数组的大小是5(动态初始化)又用大括号来指定数组大小(静态初始化)所以报错了。 3. 数组的使用
3.1 数组元素的下标访问
数组在内存中是一段连续的空间空间的编号都是从0开始的依次递增该编号称为数组的下标数组可以通过 下标访问其任意位置的元素。比如
int[]array new int[]{10, 20, 30, 40, 50};System.out.println(array[0]);System.out.println(array[1]);System.out.println(array[2]);System.out.println(array[3]);System.out.println(array[4]);// 也可以通过[]对数组中的元素进行修改
array[0] 100;System.out.println(array[0]);
tips在Java中方括号 [] 确实用于访问数组中的元素但它并不被称为“下标访问运算符”或者索引运算符。这与其他支持运算符重载的语言有所不同。Java将 [] 视为数组访问的直接语法仅用于数组并没有定义为运算符或允许重载。
【注意事项】
数组是一段连续的内存空间因此支持随机访问即通过下标访问快速访问数组中任意位置的元素。 下标从0开始介于[0, N之间不包含NN为元素个数不能越界否则会报出下标越界异常。java.lang.ArrayIndexOutOfBoundsException异常代表数组越界访问 3.2 计算数组长度 在数组中可以通过“ 数组对象.length ”来获取数组的长度。 例如 输出 为什么可以这样获得数组的长度简单了解
我们注意到我们用到了一个符号.这个符号是成员访问运算符用法就类似C语言中的结构体。Java中的对象就类似C语言的结构体但会多了很多复杂的语法比如对象中可以有方法其实在Java中使用数组时会自动导入“java.lang.reflect.Array”类。我们new的int[10]或String[4]等等其实是new了(创建了)一个Array类型的对象。而Array类中有一个成员变量length它记录着数组的长度。【可以简单得理解为C语言中的顺序表】 3.3 循环遍历数组的2种方式
\1. for语句
这是最简单的方法例如 int[] arr new int[10];
for(int i 0; i arr.length; i){System.out.println(arr[i]);
} \2. for - each语句
for-each 是 for 循环的另外一种使用方式。 语法格式 for (元素类型 变量名 : 数组名) { // 循环体 } “元素类型”是数组中元素的类型“变量名”是在每次迭代中用来引用当前元素的变量“数组名”是要遍历的数组。 注意迭代变量与数组名之间有一个冒号“ : ”。 例如 int[] arr new int[10];
for(int x: arr){System.out.println(x);
} arr数组中的每个元素都是int型所以创建的变量x是int类型的。第一次循环中x等于arr[0]第二次循环中x等于arr[1]……以此类推。 【两种遍历方式的区别】 循环条件控制 for语句中的循环条件由程序员编写可以完成更复杂的要求但也容易出错。for-each语句不需要手动管理索引使得代码的意图更加明确减少了出错的可能性但循环的条件不能手动改变。 元素访问方式 for循环中通过访问数组下标会直接对数组元素进行操作。for-each循环通过迭代变量间接访问数组元素即使发生错误操作也不会改变原数组的数据。 4. 数组是引用类型内存空间的底层知识
4.1 JVM的内存区域划分
JVM对所使用的内存按照功能的不同进行了划分主要分为5的区域 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址。虚拟机栈(JVM Stack): 与方法调用相关的一些信息每个方法在执行时都会先创建一个栈帧栈帧中包含有局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息保存的都是与方法执行时相关的一 些信息。比如局部变量。当方法运行结束后栈帧就被销毁了即栈帧中保存的数据也被销毁了。局部变量的存储、方法栈帧空间的开辟和销毁就在这里本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似。只不过保存的内容是Native方法的局部变量。在有些版本的 JVM 实现中(例如HotSpot) 本地方法栈和虚拟机栈是一起的。堆区(Heap): JVM所管理的最大内存区域。使用 new 创建的对象都是在堆上保存 堆是随着程序开始运行时而创建随着程序的退出而销毁。在运行时堆中的数据只要还有在使用就不会被销毁。方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法编译出的的字节码就是保存在这个区域。 补充一点字节码是与平台无关的中间代码表示形式。字节码是Java平台核心特性之一它的存在使得Java程序具备了高度的可移植性和灵活性。 4.2 内存分配基础类型的变量 和 引用类型的变量 基本数据类型创建的变量该变量空间中直接存放的是其所对应的数值 而引用数据类型创建的变量一般称为对象的引用其空间中存储的是对象所在空间的地址。 例如
public static void func() {int a 10;int b 20;int[] arr new int[]{1,2,3};}
在上述代码中a、b、arr都是函数内部的局部变量因此其空间都在func方法对应的栈帧中分配。(即它们的空间在栈区上)a、b是内置类型的变量因此其空间中保存的就是给该变量初始化的值。array是数组类型的引用变量其内部保存的内容可以简单理解成是数组在堆空间中的首地址而数组的本体在堆区连续存放。 引用变量并不直接存储对象本身可以简单理解成存储的是对象在堆中空间的起始地址。通过该 地址引用变量便可以去操作对象。有点类似C语言中的指针但是Java中引用要比指针的操作更简单。 4.3 数组大小可变吗 先说结论数组的大小是固定的一旦创建无法改变其大小。 public static void main(String[] args) {int arr[] new int[10];System.out.println(arr);arr new int[5];System.out.println(arr);} 可以发现虽然我们用new的方式把数组arr的大小从10改变成了5但前后两次arr存储的地址值不同了。 这说明数组的大小是无法改变的每次使用new时都会重新创建一个新的数组。 4.4 “数组1 数组2”会发生什么 arr1 arr2相当于把arr2所引用的地址交给了arr1所以现在arr1和arr2都指向了同一个数组。arr1现在改变了引用的对象如果arr1原来所引用的数组没有被其他引用变量引用则系统会自动回收该堆上的空间。 【C语言中不支持“数组1 数组2”的语法】 例如
public static void func() {int[] array1 new int[]{10,20,30};int[] array2 new int[]{1,2,3,4,5};int[] t array1;array1 array2;array2 t;for(int x:array1){System.out.print(x );}System.out.println();for (int x:array2){System.out.print(x );}}
运行结果 可以发现array1和array2所引用的对象成功被交换。 【注意事项】 在对象交换的过程中数组array1、数组array2和临时变量 t 都必须是同类型的。(刚刚的例子中它们都是int[]类型的变量) 4.5 空引用null null 在 Java 中表示 空引用 , 也就是一个不指向对象的引用. int[] arr null;System.out.println(arr[0]);// 执行结果
Exception in thread main java.lang.NullPointerExceptionat Test.main(Test.java:6)
null 的作用类似于 C 语言中的 NULL (空指针)都是表示一个无效的内存位置。 因此不能对这个内存进行任何读写操作。 一旦尝试读写就会抛出 NullPointerException。 注意事项 1. 当引用类型的变量没有new一个对象的时候必须要赋值null。 2. null不能写成NULL这是因为 NULL是“ (void*)0 ”的宏定义在Java中既没有宏定义的语法也没有指针的语法。 5. 数组 与 方法
5.1 数组作为方法参数 数组作为方法参数时形参数组要与实参数组的数组类型一致。 看一个例子
public static 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
可以发现在func方法内部修改数组的内容, 方法外部的数组内容也发生改变。 与C语言类似数组作为参数传递的也是数组的地址。 但不同的是 C语言中的形参数组是一个“伪数组”本质上是一个指针变量所以形参的类型可以用指针类型来代替而Java中的形参数组是一个“真数组”本质上是数组类型的引用变量所以形参的类型不能用其他引用类型来代替。 将数组的地址传入到函数形参中这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大)。
5.2 数组作为方法返回类型 数组作为返回值一般都是在方法内部new了一个数组对象然后返回该对象的地址。 例如 public static int[] makeIntArray(int n){int[] arr new int[n];return arr;}public static void main(String[] args) {int[] array makeIntArray(10);} 这种用法就类似C语言中给顺序表中的数组用malloc函数或colloc函数创建数组一样。 6. Arrays的一些实用工具方法
Java为我们提供了一个专门处理数组的工具类Arrays里面有一系列实用的方法。 【注意】我们本章使用的工具类是Arrays类不是Array类 数组类型是Java语言的核心部分没有特定的包路径。Array类位于 java.lang.reflect 包中主要用于反射机制中的数组操作。Arrays类位于 java.util 包中提供了更多实用的数组操作方法适用于日常开发中的数组处理需求。 它们三者都是引用类型前者是数组类型后两者属于类类型三者均无包含关系。 即使没有显式导入 Array 类你仍然可以创建和操作数组这是因为数组是Java语言的核心部分。不过Arrays需要显式导入“import java.util.Arrays”。 6.1 数组转字符串 toString方法可以把数组的信息转换为字符串。 参数是要被转化数组返回类型是字符串。原数组的信息不会被修改。 例如
public static void main(String[] args) {int[] arr new int[]{1,2,3,4,5};String str Arrays.toString(arr);//把数组转换为字符串由字符串str接收//打印数组被转换后的结果System.out.println(str);//打印原数组for(int x: arr){System.out.print(x );}}
输出结果 模拟实现Arrays.toString
public static String myToString(int[] arr){String str [;for(int i 0; i arr.length; i){str arr[i];if(i ! arr.length - 1){ //最后一个元素不要加逗号str ,;}}str ];return str;}
public static void main(String[] args) {int[] arr1 new int[]{1,2,3,4,5};String str myToString(arr1);System.out.println(str);}
输出 6.2 数组的拷贝 1. 两个参数的copyOf (数组名arr拷贝长度N) 在方法中新创建一个长度为N的数组把arr中的数据拷贝到该方法中的数组最后返回该数组的地址。从序号0一直拷贝到下标N-1处。如果长度N大于arr的大小则用默认值填充。 public static void main(String[] args) {int[] arr1 new int[]{1,2,3,4,5};int[] arr2 Arrays.copyOf(arr1,7);for(int x: arr2){System.out.print(x );}}
输出 2. 三个参数的copyOfRange(数组名arr整数1整数2) 使用方式与上面的方法类似区别是该方法是范围拷贝。拷贝范围是 [ 整数1整数2 )。左闭右开拷贝的范围如果超出arr数组的右边则用用默认值填充。 例如
public static void main(String[] args) {int[] arr1 new int[]{1,2,3,4,5};int[] arr2 Arrays.copyOfRange(arr1,3,7); //拷贝区间[3,7)for(int x: arr2){System.out.print(x );}}
输出 6.3 数组的排序 使用sort方法可以为数组排序 例如
public class Blog {public static void main(String[] args) {int[] arr {9, 5, 2, 7};Arrays.sort(arr);System.out.println(Arrays.toString(arr));}
} 6.4 二分查找指定元素 1. 两个参数的binarySearch (数组名arr, 要查找的元素key) 返回值 是key所在的序号如果找不到该元素则会返回一个负数。 例如
public static void main(String[] args) {int[] arr {0,1,2,3,4,5,6,7,8,9};int pos Arrays.binarySearch(arr,5);System.out.println(要查找的元素位于序号pos);} 二分查找方法的模拟 public static int myBinarySearch(int[] arr, int key){int left 0;int right arr.length-1;while(left right) { //如果left不能等于right的话那么当key在最右边时会误以为找不到该元素int mid (left right) / 2;if(arr[mid] key){right mid - 1;//此时要找的数据在mid左边right变成mid-1,则区间[left,right]就位于mid左边了}else if(arr[mid] key){left mid 1;//此时要找的数据在mid右边left变成mid1则区间[left,right]就位于mid右边了}else{return mid;}}return -1;}
public static void main(String[] args) {int[] arr {0,1,2,3,4,5,6,7,8,9};int pos myBinarySearch(arr,9);System.out.println(要查找的元素位于序号pos);} 2. 四个参数的binarySearch (数组名arr, 左边界k1, 右边界k2, 要查找的元素key) 效果与上一个方法类似区别是在规定范围内查找区间[ k1, k2 )。(左闭右开) 例如
public static void main(String[] args) {int[] arr {0,1,2,3,4,5,6,7,8,9};int pos Arrays.binarySearch(arr,6,9,9);//区间[6,9)System.out.println(要查找的元素位于序号pos);pos Arrays.binarySearch(arr,6,10,9);//区间[6,10)System.out.println(要查找的元素位于序号pos);} 6.5 判断两个数组是否相等 使用equals(数组1数组2)可以判断两个数组是否相等。 相等返回true不相等返回false。 例如
public static void main(String[] args) {int[] arr new int[]{1,2,3,4};int[] arr1 new int[]{1,2,3,4};int[] arr2 new int[]{1,2,3,3};System.out.println(Arrays.equals(arr, arr1));System.out.println(Arrays.equals(arr, arr2));} 6.6 填充数组元素 1. 两个参数的 fill (数组名arr填充值m) 用填充值m对数组arr中的所有元素进行赋值。该方法会直接操作数组arr。 例如 public static void main(String[] args) {int[] arr new int[]{1,2,3,4};Arrays.fill(arr,5);System.out.println(Arrays.toString(arr));} 2. 四个参数的 fill (数组名arr左边界k1右边界k2填充值m) 范围填充区间是[ k1, k2 )。 例如
public static void main(String[] args) {int[] arr new int[]{1,2,3,4};Arrays.fill(arr,1,3,6);System.out.println(Arrays.toString(arr));} 总的来说数组作为Java编程中最基本且常见的数据结构之一其重要性不言而喻。通过深入了解数组的特点、用法以及在实际应用中的优势开发者可以更好地应用它来解决问题提高代码的效率和可读性。 本期分享完毕谢谢大家的支持Thanks♪(ω)