方法(下)、内存分析、数组、交换变量的值
方法(下)
方法分类
静态方法:使用static修饰的方法是静态方法;
成员方法:没有static修饰的方法是成员方法
构造方法:创建对象使用,先不管
调用:
静态方法:类名.静态方法名(参数),同类中 类名可以省略。
成员方法:对象引用.成员方法名(参数)
方法不调用不执行,调用才执行,并把结果返回到调用处。
编写方法只考虑功能的实现,最终这个方法被用来干什么,与声明无关
入参和出参
入参是函数调用的时候,在参数列表的值,也叫实参。
出参是有返回值的函数本身。
方法重载
方法名相同,参数列表不同,列表不同分为个数不同和类型不同。
内存分析
内存分为:
静态区/方法区,vm栈,堆内存,程序计数器,本地方法栈。
静态区/方法区:
保存程序文件(class文件)以及静态数据,方法被调用之前,也保存在静态区,内部还有运行时的常量池。
vm栈:
又叫栈内存,栈内存是以数据结构为模型开辟的一段空间,特性是先进后出。栈:是一种数据结构,先进后出,像弹夹。
栈的构成因素:
栈空间:栈内存就是栈空间。
栈帧:栈空间的每一个栈元素,就叫栈帧。
栈底元素:第一个放进去的栈帧
栈顶元素:最后一个放进去的栈帧。
栈操作
压栈:就是把元素放入栈空间的过程。
弹栈:就是把元素弹出去的过程。
栈内存,是用来执行方法的,所有的方法的执行,必须在栈内存进行。
本地方法栈:
用来执行一些本地方法,比如hasCode等,模型和操作都和vm栈一致
堆内存:
用来保存对象。
程序计数器:
一块较小的内存区域.作用可以看做是当前程序执行的位置指示器
代码运行机制
java程序编写
javac编译,得到class文件
Java命令 运行
开启jvm,把运行的程序载入内存,把class文件保存到静态区
加载完之后jvm自动调用程序中的main方法
在栈内存开辟栈帧,用来执行main方法。
如果mian方法中没有其他方法调用,则运行完,弹栈销毁结束jvm关闭。
如果main方法中有其他调用,则在main方法中之上再开辟一个栈帧,用来执行新的方法,,以此类推,但是如果调用的方法是别的类中的方法,则需要把对应的类先加载进来。
方法调用:就等于压栈操作
方法执行完成:就等于弹栈操作。
加载:
静态加载:指程序开始运行,就把相关的所有文件全部一次性载入内存。
动态加载:程序运行开始,只载入核心文件,当用到其他文件的时候,再去加载
java采用的是动态加载机制。
递归
方法中调用方法,(注意每次调用,参数的变化)
递归思想
递归和迭代是等价的,就是循环
基本思想是以此类推
循环能做的,递归都能做,,但是这种情况优先使用循环,因为递归非常消耗内存运行效率低但是像树状结构之类的,循环是没法做的,只能用递归来搞定。
常见问题
所有树状结构
文件夹复制
斐波那契数列
难点不容易理解,递归思想
画图,栈帧调用图
注意必须有终止条件,否则就像死循环一样导致一直压栈不会弹栈,出现的内存溢出问题。
数组
数据结构
数据结构是计算机存储,组织数据的方式。数据结构是指相互之间存在一种或者多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或存储效率。
数据结构往往同高效的检索算法和索引技术有关。
数据操作:增删改查。
数组特性:
内存中连续储存,并且下标从零开始(内存地址偏移)
数组长度一旦确定,长度不能改变,也就意味着数组是不能添加和删除的。除非新建一个数组,把原来的数据复制到新数组中,在复制的过程中可以进行添加和删除操作。
所以 数组的查询和更改效率很高的,但是添加和删除效率较低。
数组都有一个内置属性length保存了数组的长度
在java中有一个java.util.Arrays 类提供了一些数组操作
数组声明
静态声明:在已知每个元素的时候,使用静态声明
数据类型[] 变量名 = {值1,值2,值3,……};
数据类型[] 变量名= new 数据类型[]{值1,值2,值3……}
第二次赋值:
变量名= new 数据类型[]{值1,值2,值3……}
动态声明
不知道数组中每个元素的时候,使用动态声明
数据类型[] 变量名 = new 数据类型[长度];
动态声明保存的是对应类型的默认值
整型 0 , 浮点型 0.0 , 布尔型 false , 字符 \u0000 , 引用类型 null
存储方式
数组是以引用的方式调用的,方法在栈内存里运行的时候,定义的数组是以确定地址的形式来指向一个堆内存地址空间,在堆内存地址空间里存放的是数组的数据。
获取数据:
通过下标获取,下标可以是字面量,也可以是表达式;
数组.length,获取数组长度。
更改数据:重新给指定下标赋值。
遍历:for循环或者foreach for(int elelment:数组){elemnt存有该轮循环下的元素},通过循环指定每一个下标。
常见异常
下标越界(Java.lang.ArrayIndexOutOfBoundsException)
使用了没有的下标
空指针异常(Java.lang.NullPointException)
对没有初始化的数组进行了属性操作
数组参数传递
可以直接使用数组名字传参
也可以使用字面量的方式传参,不过字面量方式不止包括字面量(new 数据类型[])
传值:基本类型在传递参数的时候一般都会传值,这样当变量在方法中被调用并改变,该变量在别的地方都不会改变。因为指向不同的空间。
传址/传引用 :因为指向的是同一个堆内存地址对象空间
数组复制
数组复制方法的要素 源数组,源数组起始位置,目标数组,目标数组起始位置,插入个数
System.arraycopy();
Main方法传参
main方法的参数列表是String类型的数组
参数之间用空格分开。
二维数组
声明方式
静态声明
int[][] arr={
{},
{},
{},
}
动态声明
int[][]arr=new int[3][4]
int[][]arr=new int[3][]表示有三个一维数组,每一个都是null,需要单独初始化。
存储方式
栈内存的方法中存储的是一维数组的地址,该地址指向的堆内存内容是第二维数组的地址,该地址指向的内容是二维数组的内容。
使用方式
获取数据
依据下标获取,下表可以是字面量或者表达式
动态声明再挨个初始化,可以形成锯齿状二位数组
交换变量的值
使用中间变量
z=x;
x=y;
y=z;
位移运算
x=x^y;
y=x^y;
x=x^y;
加减运算
x=x+y;
y=x-y;
x=x-y;