Java方法
概述
Java方法是语句的集合,它们在一起执行一个功能
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
设计方法的原则:方法的本意是功能块,也就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,也就是一个方法只完成一个功能,这样有利于我们后期的扩展。
结构
方法包含一个方法头和一个方法体,下面是一个方法的所有部分:
- 修饰符:可选,是用来告知编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型:方法可能有返回值。returnValueType是方法返回值的数据类型。有些方法执行所需要的操作,但没有返回值,这时候returnValueType的关键字是void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名
- 参数类型:参数像一个占位符当方法被调用时,传递值给实参或变量。参数列表指的是方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据
- 实参:调用方法时实际传给方法的数据
- 方法体:方法体包含具体的语句,定义该方法的功能
修饰符 返回值类型 方法名(参数类型 参数名){
方法体
return 返回值;//如果没有返回值的话,这句话就没有
}
Java只有值传递
重载
规则:
- 方法名称必须相同
- 参数列表必须不同(个数不同、或类型不同、参数排列不同等)
- 方法的返回值可以相同也可以不同
- 仅仅返回值不同不足以成为方法的重载
实现理论:
- 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
命令行传参
操作方法:
- 在.Java的文件夹下使用cmd,输入:javac 文件名.java
- 使用cd ../回退到src目录下
- 使用命令:包名 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
*/