day4 - 方法和Java内存和数组

Java方法

概述

Java方法是语句的集合,它们在一起执行一个功能

  • 方法是解决一类问题的步骤的有序组合

  • 方法包含于类或对象中

  • 方法在程序中被创建,在其他地方被引用

设计方法的原则:方法的本意是功能块,也就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,也就是一个方法只完成一个功能,这样有利于我们后期的扩展。

 

结构

方法包含一个方法头和一个方法体,下面是一个方法的所有部分:

  • 修饰符:可选,是用来告知编译器如何调用该方法。定义了该方法的访问类型。

  • 返回值类型:方法可能有返回值。returnValueType是方法返回值的数据类型。有些方法执行所需要的操作,但没有返回值,这时候returnValueType的关键字是void。

  • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名

  • 参数类型:参数像一个占位符当方法被调用时,传递值给实参或变量。参数列表指的是方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。

    • 形式参数:在方法被调用时用于接收外界输入的数据

    • 实参:调用方法时实际传给方法的数据

  • 方法体方法体包含具体的语句,定义该方法的功能

修饰符 返回值类型 方法名(参数类型 参数名){
   方法体
   return 返回值;//如果没有返回值的话,这句话就没有
}

Java只有值传递

 

重载

规则:

  • 方法名称必须相同

  • 参数列表必须不同(个数不同、或类型不同、参数排列不同等)

  • 方法的返回值可以相同也可以不同

  • 仅仅返回值不同不足以成为方法的重载

实现理论:

  • 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。

 

命令行传参

操作方法:

  1. 在.Java的文件夹下使用cmd,输入:javac 文件名.java

  2. 使用cd ../回退到src目录下

  3. 使用命令:包名 java 文件名+传入的参数

 

可变参数

  • 从JDK1.5 开始,Java支持传递同类型的可变参数给一个方法。

  • 在方法声明中,在指定参数类型后加一个省略号(...)。

  • 一个方法只能制定一个可变参数,它必须是方法的最后一个参数。任何普通参数都必须在它之前声明,形如:

public class hello {
   public static void main(String[] args) {
       hello a = new hello();
       a.max(1,2,7,8,9,5,454,1);
  }
   public  void max(double... num){
       if(num.length == 0){
           System.out.println("数组越界了");
           return;
      }
       double result = num[0];
       //排序
       for (int i = 1; i < num.length; i++) {
           if(num[i]>result){
               result = num[i];
          }
      }
       System.out.println("max is "+ result);
  }
}
//结果是max is 454.0
//如果方法调用的是a.max();结果则为“数组越界了”

 

递归

递归结构:

  • 递归头:什么时候不调用自身方法。如果没有头将陷入死循环。

  • 递归体:什么时候需要调用自身方法。

以计算5!为例:

public class hello {
   public static void main(String[] args) {
       hello a = new hello();
       System.out.println(a.f(5));
  }
   public int f(int n){
       if(n == 1){
           return 1;//f(1)为边界条件即递归头,也就是该递归停止的条件
      }else{
           return n*f(n-1);//这个就是递归体
      }
  }
}
//延伸:从Java的栈机制分析,首先将f(5)压进栈,然后把f(4)压进栈,以此类推直到f(1),取出f(1)的值,然后取出f(2)的值,类推,最后取出f(5)的值,得到结果。

 

Java内存

基本概念

Java内存分为三个部分:

堆(heap)

  • 存放new的对象,每个对象都包含一个与之对应的class信息。(class的目的是得到操作指令)

  • jvm只有一个heap区,被所有的线程共享,不存放基本类型和对象引用,值存放对象本身。

  • 堆的优势:可以动态的分配内存大小,生存期也不必事先告诉编译器,.java的垃圾回收期会自动收取这些不在使用的数据

  • 堆的缺点:由于要在运行时动态分配内存,存取速度慢。

栈(stack)

  • 每一个线程包含一个stack区,只保存基本数据类型(包含这个基本类型的具体数值)和自定义对象的引用(不是对象,存放的是这个引用在堆里面的具体地址)。

  • 每个栈中的数据(基本数据类型和对象的引用)都是私有的,其他栈不能访问。(单个stack的数据可以共享)

  • 栈分为3个部分:基本数据类型的变量区、执行环境上下文、操作指令区(存放操作指令)。

  • 栈的优势:存取速度比堆快,仅次于直接位于CPU的寄存器,但必须确定是存在stack中的数据大小与生存期必须是确定的。

  • 栈的缺点:缺乏灵活性。

  • stack是一个先进后出的数据结构。

方法区(method)

  • 和堆一样,被所有线程共享。

  • 包含了所有的class和static变量。

  • 方法区包含的都是程序中永远唯一的元素。(这也是方法区被所有的线程共享的原因)

从数组分析Java内存

数组创建方式:

//原型:
dataType[] arrayRefVar = new dataType[arraySize];
//实例:
int[] array = new int[10];//数组的值默认初始化都为0

1、声明数组

int[] array = null;

2、创建数组

array = new int[10]

3、给数组元素中赋值

for(int i = 0;i<10;i++)
   array[i] = i;

具体过程如图:

 

打印数组

for each循环

int[] array = {1,5,6,7,5};
for (int i : array) {
           System.out.print(i+"\t");//打印出15675
      }
//这个方法缺点在于无法选择下标,一般只适合把数组打印出来

 

Arrays.toString方法

因为Arrays是一个自带的静态类,所以可以直接引用它的toString方法

public static void main(String[] args) {
       int [] a = {1,5,16,1,4};
       System.out.println(a);//打印出的是一个hashcode [I@10f87f48
       System.out.println(Arrays.toString(a));//[1, 5, 16, 1, 4]
  }

 

稀疏数组

当一个数组中大部分元素为0,或者为同一数值时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方式:

  • 记录数组一共有几行几列,有多少个不同的值。

  • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模。

例如:

   
0 0 0
  0 0 0
  0 7 0
  0 0 8

变成稀疏数组:

 

index行(0开始计数)
[0] 4 3 2
[1] 2 1 7
[2] 3 2 8

代码形式:

 

    public static void main(String[] args) {
       int [][] array1 = new int [4][3];
       array1[2][1] = 7;
       array1[3][2] = 8;
       //打印原本数组
       System.out.println("原本数组");
       for (int[] ints:array1) {
           for (int anInt:ints) {
               System.out.print(anInt + "\t");
          }
           System.out.println();
      }
       //转换成稀疏数组
       //获取有效值个数
       int sum = 0;
       for (int i = 0; i < 4; i++) {
           for (int j = 0; j < 3; j++) {
               if(array1[i][j]!=0)
                   sum++;
          }
      }
       //创建一个稀疏数组
       int[][] array2 = new int[sum+1][3];
       array2[0][0] = 4;
       array2[0][1] = 3;
       array2[0][2] = sum;

       //遍历二维数组,将非零的值存放到细数数组中
       int count = 0;
       for (int i = 0; i < array1.length; i++) {
           for (int j = 0; j < array1[i].length; j++) {
               if(array1[i][j]!=0){
                   count++;
                   array2[count][0] = i;
                   array2[count][1] = j;
                   array2[count][2] = array1[i][j];
              }
          }
      }
       //打印稀疏数组
       System.out.println("稀疏数组");
       for (int[] ints:array2) {
           for (int anInt:ints) {
               System.out.print(anInt + "\t");
          }
           System.out.println();
      }

       //还原数组
       //读取稀疏数组
       int[][] array3 = new int[array2[0][0]][array2[0][1]];
       
       //给其中元素还原他的值
       for(int i =1;i < array2.length; i++){
           array3[array2[i][0]][array2[i][1]] = array2[i][2];
      }
       //打印还原数组
       System.out.println("还原数组");
       for (int[] ints:array3) {
           for (int anInt:ints) {
               System.out.print(anInt + "\t");
          }
           System.out.println();
      }
  }
/*输出结果为
原本数组
000
000
070
008
稀疏数组
432
217
328
还原数组
000
000
070
008
*/
posted @ 2020-10-19 21:11  NSFW  阅读(116)  评论(0)    收藏  举报