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;

具体过程如图:

Java 计算字节数组所占内存 java 数组 内存_数组

 

打印数组

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
*/