一 ,Java的内存分配
每种软件在运行时都会占用一片内存区域,Java也不例外,Java虚拟机会占用一片空间。
为了更好地利用这片空间,jvm把这片空间分为5大部分,每个部分都有自己独立的各自的作用。
在jvm中有独立的五个部分分别为:本地方法栈,寄存器,栈,堆,元空间
1.1本地方法栈
存储JNI方法的调用信息。
存储本地方法中的局部变量,操作栈等信息。
在执行本地方法时,本地方法栈会为本地代码分配内存并记录调用信息。与 Java 方法栈不同,本地方法栈执行的不是 JVM 字节码,而是本地机器代码
1.2寄存器
通常是指用于存储执行 Java 字节码指令时临时数据的硬件级存储单元。
1.3JVM 栈(Java Virtual Machine Stack)
是用于存储方法的局部变量、操作数栈、方法调用的执行状态等数据的内存区域。JVM 栈是每个线程私有的,也就是说,每个线程在 JVM 中都有一个独立的栈,它由多个 栈帧(Stack Frame)组成。每当一个方法被调用时,JVM 会为该方法创建一个新的栈帧,并将其压入栈中;当方法执行完毕时,栈帧会被1.3JVM 栈(Java Virtual Machine Stack)
是用于存储方法的局部变量、操作数栈、方法调用的执行状态等数据的内存区域。JVM 栈是每个线程私有的,也就是说,每个线程在 JVM 中都有一个独立的栈,它由多个 栈帧(Stack Frame)组成。每当一个方法被调用时,JVM 会为该方法创建一个新的栈帧,并将其压入栈中;当方法执行完毕时,栈帧会被弹出(弹栈)
变量都存在栈中(基本数据类型的直接存数据,引用数据类型的存引用地址,数据在引用地址对应的堆中存放)
1.4**JVM 堆(Heap)
只要是new出来的 都存在堆中!!!
是 JVM 中用于存储对象和数组的内存区域。堆是所有线程共享的内存区域,Java 中的对象和数组通常都分配在堆中,而局部变量和方法调用等数据则存储在 JVM 栈 中。堆是 Java 内存管理的关键部分,负责为对象的实例分配内存并通过 垃圾回收(GC)来管理内存的释放。
总结: 只要是new 出来的都要存放到堆中(new出来的就是引用类型的例如String类和数组等)
在堆区中也有内存地址, 和栈区内存地址是一样的!!
1.5最简单的代码的内存
现在只需要关注 栈和堆 这来两个内存,如果没有new,则只需要关注栈区
1.6数组的内存占用
数组在栈中存放的是一串内存地址,如果直接打印也只会是一串地址数字,它的数据存放在堆中地址对应的位置,使用Arrays.toString()这个方法能将其打印出来。
二,数组的应用
2.1数组可以当方法参数
由于数组本身就是一种引用类型,因此可以直接当作方法的参数使用。
public class Demo { //这是一个参数为数组无返回值的方法, public static void count(int[] arr){ //上面参数为形参,即形式参数,无确定的值 for (int i = 0; i < arr.length; i++) { arr[i]++; } System.out.println(Arrays.toString(arr)); } public static void main(String[] args) { int[] arr={1,2,3,4,5};//定义了一个数组 System.out.println(Arrays.toString(arr));//打印原数组 count(arr);//方法参数的数据类型是什么,这里调用方法的参数类型也一样,这里赋予了个实参,让其运行方法 } }
2.2数组当返回值类型
public class Demo2 { //这是一个无参返回值类型为字符串数组的方法 public static String[] sp(){ String[] home={"历史","灰烬","烟火","袅袅","停渡"}; return home;//返回了一个数组 } public static void main(String[] args) { String[] work=sp();//在主函数中调用方法后用一个相同类型(同为字符串类型的数组)的变量接住方法的返回值 System.out.println(Arrays.toString(work));//打印数组 }
三,引用数据类型
java的数据类型
-
基本数据类型: 四类八种
-
引用数据类型: 数组,类,接口 String是一个类
Java的内存,了解栈堆
方法执行进栈,执行完弹栈,new的对象进堆
-
nt[] arr = new int[4]; sout(arr) 0xac2889 就叫 对象的引用
-
引用就是内存地址值,通过引用找到堆中的对象
-
引用类型对象在堆中,基本类型变量在栈中
-
引用类型方法传参时,传递是地址值
-
基本类型方法传参时,传递是数值
-
每个方法都是独立的
-
方法内的变量和其他方法没关系
3.1基本类型是值的传递
基本数据类型在方法传递参数
-
基本数据类型是数据本身(值本身)在传递
-
且基本类型数据存在于方法的栈中
-
方法执行完弹栈消失,方法内的变量也随之消失
将一个基本数据类型的变量的值赋给另外一个变量,操作另外一个变量不会影响原本的变量。这就是只传递值
3.2引用类型
引用类型在方法传参数时
-
传递是对象的地址值,即引用
-
方法接收引用后,通过引用(内存地址)找到堆中对象,改变它
-
方法执行完弹栈,堆中对象还在
引用的数据类型在栈中存放的是一个引用地址,如果直接赋值,例如:int[] arr2=arr1,是将arr1的引用地址赋给了arr2,如果你操作arr2的数据,会直接改变引用地址对应的堆中数据,arr1的值也就改变了,
四,排序算法
排序算法
-
冒泡排序,选择排序,插入排序
-
快速排序,堆排序,希尔排序,归并排序
-
桶排序,基数排序,计数排序
下面是几种简单的排序方法
4.1冒泡排序
思路:相邻的两个数据两两比较,把大数不断往后放,交换位置,依次循环排序下去。
public class Homework_effer { public static void main(String[] args) { int[] arr = {4, 1, 3, 5, 2}; int center = 0;//交换位置的中间数 for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length-1-i; j++) { if (arr[j]>arr[j+1]) { center=arr[j]; arr[j]=arr[j+1]; arr[j+1]=center; //两两相邻数比较,大数往后放 } //不断循环,将未排序数组中的大数往后放 } } System.out.println(Arrays.toString(arr)); } } /*i=0 0<5-1=4 true * j=0 0<5-1-0 true arr[0]>arr[1] 4>1 true 交换0,1 {1,4,3,5,2} j++ * j=1 1<4 true arr[1]>arr[2] 4>3 true 交换1,2 {1,3,4,5,2} j++ * j=2 2<4 true arr[2]>arr[3] 4>5 false {1,3,4,5,2} j++ * j=3 3<4 true arr[3]>arr[4] 5>2 true 交换3,4 {1,3,4,2,5} j++ * j=4 4<4 false 内层循环结束 i++ * i=1 1<4 true * j=0 0<5-1-1=3 true arr[0]>arr[1] 1>3 false {1,3,4,2,5} j++ * j=1 1<5-1-1=3 true arr[1]>arr[2] 3>4 false {1,3,4,2,5} j++ * j=2 2<5-1-1=3 true arr[2]>arr[3] 4>2 true 交换2,3 {1,3,2,4,5} j++ * j=3 3<3 false 内层循环结束 i++ * i=2 2<4 true * j=0 0<5-1-2=2 true arr[0]>arr[1] 1>3 false {1,3,2,4,5} j++ * j=1 1<5-1-1=2 true arr[1]>arr[2] 3>2 true 交换1,2 {1,2,3,4,5} j++ * j=2 2<5-1-1=2 false 内层循环结束 i++ * i=3 3<4 true * j=0 0<5-1-3=1 true arr[0]>arr[1] 1>2 false {1,2,3,4,5} j++ * j=1 1<1 false 内层循环结束 i++ * i=4 4<4 false 循环结束 * sout[1,2,3,4,5] * */
4.2选择排序
public class Homework_choice { public static void main(String[] args) { int[] arr={3,2,1,5,6,7}; int center=0;//交换位置的中间数 for (int i = 0; i < arr.length; i++) { for (int j = i; j <arr.length ; j++) { if (arr[i] < arr[j]) { center=arr[i]; arr[i]=arr[j]; arr[j]=center; //将其arr[i]与其后的每个数字比较,一旦有大于它的,就让其两方换位,将选出的大数排在前面 } //循环排列后面未排序的数据,一次选出其中最大数放在已排序数后面 } } System.out.println(Arrays.toString(arr)); } }
五,数组拷贝
5.1 自己手动实现
// 数组拷贝方式1:自己实现 public static void arrayCopyByMySelf() { // 将arr1数组的元素拷贝到arr2中 int[] arr1 = {4,2,5,1,3}; // 创建arr2数组 int[] arr2 = new int[arr1.length]; // 开始拷贝 for (int i = 0; i < arr1.length; i++) { arr2[i] = arr1[i]; } // 拷贝完,查看arr2的效果 for (int i = 0; i < arr2.length; i++) { System.out.println(arr2[i] ); } }
5.2 Arrays.copyOf
Arrays是jdk提供的类用来操作数组的,copyOf 用来拷贝数组的
// 数组拷贝方式2:通过Arrays实现 public static void arrayCopyByArrays() { // 将arr1数组的元素拷贝到arr2中 int[] arr1 = {4, 2, 5, 1, 3}; // 使用Arrays.copyOf方法 // 参数1是要拷贝的数组 // 参数2是要生成的数组的长度 int[] arr2 = Arrays.copyOf(arr1, arr1.length-2); // 拷贝完,查看arr2的效果 for (int i = 0; i < arr2.length; i++) { System.out.println(arr2[i]); } }
5.3 System.arraycopy
System是jdk提供的类,其中方法arraycopy完成数组拷贝
// 数组拷贝方式3:通过System实现 public static void arrayCopyBySystem() { // 将arr1数组的元素拷贝到arr2中 int[] arr1 = {4, 2, 5, 1, 3}; int[] arr2 = new int[arr1.length]; /** * 参数1: 拷贝源数组 * 参数2: 从源数组哪里开始拷贝(位置下标) * 参数3: 目的地数组 * 参数4: 将数组放到目的地数组的哪个位置(下标) * 参数5: 拷贝多少个 */ System.arraycopy(arr1,1,arr2,1,3); // 拷贝完,查看arr2的效果 for (int i = 0; i < arr2.length; i++) { System.out.println(arr2[i]); } }
六、数组扩容
数组本身确定是不能扩容的,此处这个"数组扩容"是指重新创建更大的数组,将之前数组元素拷贝到新数组中,接着去使用新的大数组去存储数据,感觉上是 数组扩容了.... 其实创建是了更大的新数组
package com.qf.array; /** * --- 天道酬勤 --- * * @author QiuShiju * @date 2024/2/27 * @desc 数组扩容 */ public class Demo5 { public static void main(String[] args) { int[] arr = {1,2,3,4,5}; System.out.println("arr第一次的地址:"+arr ); System.out.println("扩容前arr: " ); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] +" "); } System.out.println( ); // 扩容 arr = changeSize(arr);// 将返回的新数组的地址赋值给arr System.out.println("arr第二次的地址:"+arr ); // 扩容后重写看效果 System.out.println("扩容后arr: " ); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] +" "); } } // 这个方法可以将数组长度扩大1倍 public static int[] changeSize(int[] a) { // 扩容就是创建更大数组 int[] newArr = new int[a.length * 2]; // 将源数组元素拷贝到新数组中 System.arraycopy(a,0,newArr,0,a.length); // 返回创建的大数组 return newArr; } }
七、Arrays
Arrays是java提供一个类,专用于操作数组,常用的方法
copyOf() 数组拷贝
toString(数组); 将数组以字符串的返回
sort(数组); 将数组按照升序排序
// toString (重点)
public static void main(String[] args) { int[] arr = {1,2,3,4}; // toString(数组); 将数组以字符串形式返回 // 方法需要通过类名.方法调用 String s = ArSrays.toString(arr); System.out.println(s ); // [1,2,3,4] }
// sort
// 使用sort完成数组排序 Arrays.sort(arr); // 排序完,再看一遍 System.out.println(Arrays.toString(arr) );