一、数组
(一)JVM的内存划分
1、JVM是执行Java代码的容器,空间比较大,需要划分为不同的区域,每一个区域都有不同的功能,也具有不同的特点
2、分类:
(1)栈内存【常用】:用于执行方法的区域,每一个方法要执行的时候,都会为方法在栈内存中开辟一块空间,这个空间被称为栈帧,将方法加载分配内存空间的过程称之为:进栈;特点:先进后出
(2)堆内存【常用】:用于存储数组,对象等数据量比较大的数据,这些数据类型都是引用数据类型
(3)方法区【常用】:用于存储字节码对象、文件、.class的地方,存储静态相关的内容和常量池
(4)本地方法区:用于执行本地方法的区域,C、C++相关的方法,就是本地方法
(5)程序计数器:用于控制代码执行流程的区域
(二)两个数组指定同一个地址
二、数组的异常
(一)数组索引越界异常
1、Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
异常 在 线程 主 数组 索引 在...之外 边界 异常
2、处理方式:
(1)产生原因:访问的索引超出了已有索引的范围
(2)避免方式:尽量不要去访问索引以外的元素
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
}
(二)空指针异常
1、Exception in thread "main" java.lang.NullPointerException
异常 在 线程 主 空 指针 异常
2、处理方式
(1)出现原因:数组为空的时候,去访问数组中的元素
(2)避免方式:在访问数组之前,先判断数组是否为空
public static void main(String[] args) {
int[] arr = null;
System.out.println(arr[0]);
}
三、数组的操作
(一)数组的遍历
1、遍历:一个一个遍历元素,所有的元素都访问一遍
2、方式:
(1)访问数组中的每一个元素是在做重复的工作,使用循环进行遍历
(2)数组的索引一直在变化,使用循环的初始化变量表示索引
(3)索引的起始为0
(4)索引的终点为【数组的长度-1】
(5)数组获取长度的方法:数组名.length
public static void main(String[] args) {
int[] arr = {1, 54, 57, 78, 42, 67, 90, 61, 28, 39};
//第一种遍历
for (int i = 0; i <= arr.length - 1; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
//第二种遍历
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
(二)获取数组最值
1、给定一个数组获取数组中的最大值或者最小值
2、思路:先定义第一个元素为最大值,使用循环遍历数组,用其它元素跟最大值进行比较,如果比最大值大,就将新的最大值赋值给max,直到循环遍历结束
public static void main(String[] args) {
int[] arr = {12,34,23,25,35,65,75,87,32,54};
getMax(arr);
getMin(arr);
}
//获取最小的方法
public static void getMin(int[] arr){
int min = arr[0];
for (int i=0;i<arr.length;i++){
if (min>arr[i]){
min = arr[i];
}
}
System.out.println(min);
}
//获取最大的方法
public static void getMax(int[] arr){
int max = arr[0];
for (int i=0;i<arr.length;i++){
if (max<arr[i]){
max = arr[i];
}
}
System.out.println(max);
}
(三)数组的反转
1、将数组中的元素第一个和最后一个元素进行位置的交换,第二个和倒数第二个进行交换,以此类推
2、思路:在循环中定义两个变量,一个表示起始索引,一个表示结束索引,一个递增,一个递减,使用中间变量,让每一组首尾元素进行交换
public static void main(String[] args) {
int[] arr = {12,34,23,25,35,65,75,87,32,54};
printArr(arr);
System.out.println();
for (int i=0,j=arr.length-1;i<j;i++,j--){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
printArr(arr);
}
public static void printArr(int[] arr){
for (int i=0;i<arr.length;i++){
System.out.print(arr[i] + " ");
}
}
(四)数组的查找
题目:给定一个数组,给定一个数据,在数组中查找指定数据对应的索引并打印,如果查找不到,就返回-1
public static void main(String[] args) {
int[] arr = {12,34,23,25,35,65,75,87,32,54};
System.out.print(chaZhao(arr,32));
}
public static String chaZhao(int[] arr,int ele){
//做判断是否为空数组
if (arr != null){
for (int i=0;i<arr.length;i++){
if (arr[i]==ele){
return i + "";
}
}
return -1 + "";
}else {
return "数组为空无法查找";
}
}
(五)补充
重载:在同一个类中,方法名称相同,参数列表不同,与返回值类型无关
参数列表不同分为:个数、类型、顺序的不同
四、二维数组
(一)概述
1、概述:二维数组其实就是数组的嵌套,二维数组中存储的是一维数组的地址,一维数组中存储的才是真实的数据
2、定义格式
int[][] arr = new int[2][3];
表示创建了一个二维数组,二维数组中可以存储2个一维数组,每一个一维数组中可以存储3个数据
(二)遍历
说明:外层循环遍历的是二维数组中所有的一维数组(也就是地址值),内存循环遍历的是每一个一维数组中的元素(真实数据)
public static void main(String[] args) {
int[][] arr = {
{12,14,43},
{43,65,75,86},
{},
null,
{22,44,77}
};
for (int i=0;i<arr.length;i++){
System.out.println(arr[i]);
if (arr[i] != null){
for (int j=0;j<arr[i].length;j++){
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
}
五、递归
1、概述:方法自己调用自己就是递归
2、需要有结束标志
3、调用
(1)直接调用:A方法调用B方法,B方法调用A方法
(2)间接调用:A方法调用B方法,B方法调用C方法,C方法调用A方法
/**斐波那契数列 1 1 2 3 5 8 13 21 34 55 ...
* 打印第num个数
*/
public class Demo01 {
public static void main(String[] args) {
int num = fibonacci(6);
System.out.println(num);
}
public static int fibonacci(int num){
if (num==1 || num==2){
return 1;
}
return fibonacci(num-2)+fibonacci(num-1);
}
}
六、面向对象
1、面向对象:就是一种编程思想
2、面向过程和面向对象
(1)面向过程:强调做事情的基本步骤,调用解决问题的具体方式,面向对象是基于面向过程的
(2)面向对象:强调是做事情的主体,更强调谁来解决问题,强调的是数据,以及谁拥有数据和操作数据的权利
3、面向对象的好处:
(1)更符合现代人的习惯:方便
(2)复杂问题简单化
(3)由执行者变成了指挥者
4、特点:
(1)封装
(2)继承
(3)多态
课后练习:
/**分析以下需求,并用代码实现:(封装成方法)
* (1)打印1到100之内的整数,但数字中包含m的要跳过
* (2)每行输出n个满足条件的数,之间用空格分隔
* (3)如:
* 1 2 3 4 5
* 6 7 8 10 11
*/
public class Test01 {
public static void main(String[] args) {
print1();
System.out.println();
print2();
}
//打印1到100之内的整数,但数字中包含m的要跳过
public static void print1(){
int m = 3;
for (int i=1;i<=100;i++){
if(i/100%10 != m && i/10%10 != m && i%10 != m){
System.out.print(i+" ");
}
}
}
//每行输出n个满足条件的数,之间用空格分隔
public static void print2() {
int m = 3;
int n = 5;
int i = 1;
int count = 0;//计数
while (i<=100){
if(i/100%10 != m && i/10%10 != m && i%10 != m){
System.out.print(i+" ");
count++;
}
if (count == n){
System.out.println();
count = 0;
}
i++;
}
}
}
/**银行ATM机存取款案例
*/
public class Test02 {
//声明全局变量,初始化用户余额
public static double z = 0;
public static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("*************************************");
System.out.println(" 欢迎使用森狗银行ATM自动操作柜员机 ");
System.out.println("*************************************");
choose();
}
//选择
public static void choose(){
System.out.print("请选择功能(1.存钱 2.取钱 3.查询余额 4.退出):");
menu();
}
//功能
public static void menu(){
int a = sc.nextInt();
switch (a){
case 1:
saveMoney();
break;
case 2:
catchMoney();
break;
case 3:
showMoney();
break;
case 4:
exit();
default:
System.out.print("输入的选项有误,请重新输入(1.存钱 2.取钱 3.查询余额 4.退出):");
menu();
}
}
//存钱
public static void saveMoney(){
System.out.print("请输入存入的金额:");
double b = sc.nextInt();
z = z+b;
System.out.println(b+"元存入成功,余额为"+z+"元");
choose();
}
//取钱
public static void catchMoney(){
System.out.print("请输入取出的金额:");
double b = sc.nextInt();
if (b<=z){
z = z-b;
System.out.println("本次取出"+b+"元,余额为"+z+"元");
}else {
System.out.println("余额不足,请重新输入金额进行取钱");
catchMoney();
}
choose();
}
//查询余额
public static void showMoney(){
System.out.println("账户余额为"+z+"元");
choose();
}
//退出
public static void exit(){
System.out.println("程序已退出,请取回您的银行卡");
System.exit(0);
}
}