java内存划分
为什么要划分那?
他的道理根房子是一样的,通过一道墙来区别功能区.
java的内存需要划分成为5个部分:
1.栈(Stack):存放的都是方法中的局部变量.方法的运行一定要在栈当中
局部变量:方法的参数,或者是方法{}内部的变量
作用域:一旦超出作用域,立刻从栈内存当中消失.
2.堆内存(Heap):凡是new出来的东西,都在堆当中
堆内存里面的东西都有一个地址值:16进制
堆内存里面的数据,都有默认值.规则:
如果是整数 默认为0
如果是浮点数 默认为0.0
如果是字符 默认为’\u0000’
如果是布尔 默认为false
如果是引用类型 默认为null
3.方法区(Method Area):存储.class相关信息,包含方法的信息.
4.本地方法栈(Native Method Stack):与操作系统相关.
5.寄存器(pc Register):与CPU相关
一个数组的内存图
public class t1 {
public static void main(String[] args) {
int[] array = new int[3];
System.out.println(array); //地址值
System.out.println(array[0]); //0
System.out.println(array[1]); //0
System.out.println(array[2]); //0
//改变其中元素
array[0] = 10;
array[1] = 20;
System.out.println(array); //地址值
System.out.println(array[0]); //10
System.out.println(array[1]); //20
System.out.println(array[2]); //0
}
}
两个数组内存图
public class t1 {
public static void main(String[] args) {
int[] array = new int[3];
System.out.println(array); //地址值
System.out.println(array[0]); //0
System.out.println(array[1]); //0
System.out.println(array[2]); //0
//改变其中元素
array[0] = 10;
array[1] = 20;
System.out.println(array); //地址值
System.out.println(array[0]); //10
System.out.println(array[1]); //20
System.out.println(array[2]); //0
int[] arrayA = new int[3];
System.out.println(arrayA); //地址值
System.out.println(arrayA[0]); //0
System.out.println(arrayA[1]); //0
System.out.println(arrayA[2]); //0
//改变其中元素
arrayA[0] = 100;
arrayA[1] = 200;
System.out.println(arrayA); //地址值
System.out.println(arrayA[0]); //100
System.out.println(arrayA[1]); //200
System.out.println(arrayA[2]); //0
}
}
两个引用指向同一个数组
public class t1 {
public static void main(String[] args) {
int[] array = new int[3];
System.out.println(array); //地址值
System.out.println(array[0]); //0
System.out.println(array[1]); //0
System.out.println(array[2]); //0
//改变其中元素
array[0] = 10;
array[1] = 20;
System.out.println(array); //地址值
System.out.println(array[0]); //10
System.out.println(array[1]); //20
System.out.println(array[2]); //0
//将array数组的地址值,赋值给arrayA数组
int[] arrayA = array;
System.out.println(arrayA); //地址值
System.out.println(arrayA[0]); //10
System.out.println(arrayA[1]); //20
System.out.println(arrayA[2]); //0
//改变其中元素
arrayA[0] = 100;
arrayA[1] = 200;
System.out.println(arrayA); //地址值
System.out.println(arrayA[0]); //100
System.out.println(arrayA[1]); //200
System.out.println(arrayA[2]); //0
}
}
两个常见异常类型
1.数组索引越界异常
如果访问数组元素的时候,索引编号并不存在,那么将会发生数组索引越界异常 ArrayIndexOutOfBoundsException
原因:索引编写写错了
解决:修改成为正确索引编号
public class t1 {
public static void main(String[] args) {
int[] array = {10,25,35};
System.out.println(array[0]); //10
System.out.println(array[1]); //25
System.out.println(array[2]); //35
//错误写法:并不存在3号元素
System.out.println(array[3]);
}
}
返回结果
2.空指针异常
数组必须进行new初始化才能使用其中的元素,如果只是赋值了一个null,没有进行new创建,那么将会发生:
空指针异常 NullpointerException
原因:忘了new
解决:补上new
public class t1 {
public static void main(String[] args) {
int[] array = null;
System.out.println(array[0]);
}
}
常用的数组的操作方式
获取数组长度
如何获取数组的长度,格式:
数组名称.length
将会得到一个int数组,代表数组的长度
数组一旦创建,程序运行期间,长度不可改变
public class t1 {
public static void main(String[] args) {
int[] array = new int[3];
int[] arrayB = {10,20,30};
int len = arrayB.length;
System.out.println("arrayB的长度是"+ len);
//
int[] arrayC = new int[3]; //左边是名称(或者叫做索引计数),右边才是真正的数组
System.out.println(arrayC.length); //3
arrayC = new int[5];
System.out.println(arrayC); //5
}
数组的遍历输出
public class t1 {
public static void main(String[] args) {
int[] array = {15,25,30};
//array.fori
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
求数组中的最大值
public class t1 {
public static void main(String[] args) {
int[] array = {5,15,30,20,1000};
int max = array[0];
for (int i = 0; i < array.length; i++) {
if (array[i]>max){
max = array[i];
}
}
System.out.println("最大值:"+max);
}
}
数组元素反转
1.数组元素反转,其实就是对称位置的元素交换
2.现在表示对称位置需要两个索引:
int min = 0;
int max = array.length -1;
3.如何交换两个变量的值?
int a = 10;
int b = 20;
如果是两个水杯,都是满的,如何交换?借助第三个空杯子.
int temp = a;
a = b;
b = temp;
用第三个变量倒手
4.什么时候停止交换
min >= max ==> min < max
public class t1 {
public static void main(String[] args) {
int[] array = {10,20,50,80,25};
/*
初始化语句:int min = 0,max = array.length-1
条件判断:min<max
步进表达式:min++,max--
循环体:用第三个变量倒手
*/
for (int min = 0,max = array.length-1;min<max;min++,max--) {
int temp = array[min];
array[min] = array[max];
array[max] = temp;
}
for (int i1 = 0; i1 < array.length; i1++) {
System.out.println(array[i1]);
}
}
}
数组作为方法的参数
当调用方法的时候,向方法的小括号进程传参,传递进去的其实是数组的地址值
public class t1 {
public static void main(String[] args) {
int[] array = {10,20,70,90};
printArray(array);
}
/*
方法三要素:
返回值类型:void
方法名称:printArray
参数列表:int[] array
*/
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
数组作为返回值
使用场景:
一个方法可以有多个参数,但是只能有0或者1个返回值,不能有多个返回值.如果希望一个方法当中产生了多个结果数据进行返回,怎么办?
解决方案:使用一个数组作为返回值类型即可
这种返回方式与python的元组数据类型基本相似
数组作为方法的返回值,返回的其实也是数组的地址值.
public class t1 {
public static void main(String[] args) {
int[] result = calculate(4,5,6);
System.out.println("总和"+ result[0]);
System.out.println("平均数"+ result[1]);
}
public static int[] calculate(int a,int b,int c){
int sum = a+b+c;
int avg = sum/3;
//希望两个结果都进行返回
int[] array = {sum,avg};
return array;
}
}