java基础中(笔记)
方法是用来完成特定功能的片段代码
结构
public 【修饰符】 int 【返回值类型】 add【方法名】(int 【参数类型】 a 【参数名】,int b){
int c=0; c=a+b;//方法体
return c;//返回值
}
修饰符
定义该方法的访问类型
public,protected(受保护的访问修饰符),default(默认,仅当前包),private(仅当前类)
成员变量一般是private,为了让外界去修改对象的属性从而提供了get和set方法,这也是一种封装
protected(当前包以及其他包继承该方法的子类):
子类与父类不在同一包中,子类实例可以访问其从父类继承而来的 protected 方法,而不能访问父类实例的protected方法。
返回值类型
方法可能返回的值类型,如果为void则表示没有返回值,方法体已经完成了方法的功能
方法名
方法实际的名称
参数类型
参数的类型,由方法编写者定义,方法可以不包括任何参数
形式参数
方法编写阶段,参数类型和参数名构成了形式参数
实参
方法被调用是传递的真实数据就是实参
!可变参数
在指定的参数类型后加...表示可变参数,一个方法中只能有一个可变参数且位于最后一个参数
例子:
public class demo01 {
//int... b中b就相当于一个数组
public void put(int a,int... b){
System.out.println(a);
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
}
//调用它
public static void main(String[] args){
demo01 demo01=new demo01();
demo01.put(1,4,3,2,1);
}
}
方法体
方法体就是该方法完成功能的代码片段
static(静态)
静态方法是随着类的加载而产生的,所以类或者对象可以直接调用静态方法,而非静态方法是随着对象创建而创建的,所以只能借助对象来调用
静态方法是类的方法,非静态方法是对象的方法
静态的成员变量与非静态的成员变量的区别
作用上的区别:
-
静态的成员变量的作用共享一个数据给所有的对象使用。
-
非静态的成员变量的作用是描述一类事物的公共属性。
数量与存储位置上的区别:
-
静态成员变量是存储方法区内存中,而且只会存在一份数据。
-
非静态的成员变量是存储在堆内存中,有n个对象就有n份数据。
生命周期的区别:
-
静态的成员变量数据是随着类的加载而存在,随着类文件的消失而消失。
-
非静态的成员数据是随着对象的创建而存在,随着 对象被垃圾回收器回收而消失。
static什么时候修饰一个方法
如果一个方法没有直接访问到非静态的成员时,那么就可以使用static修饰了。 一般用于工具类型的方法
静态方法不能访问非静态的成员?
静态方法只要存在有对象,那么也可以访问非静态的数据。只是不能直接访问而已。
因为静态方法是随着类的加载而产生的,所以类或者对象可以直接调用静态方法,而非静态方法是随着对象创建而创建的,所以只能借助对象来调用
static方法为什么只能调用static方法?
以为静态方法是和类一起加载到方法区的,先于对象的加载
重载
在同一类中有相同的名称的方法,但需传递的参数不同
规则
-
方法名一致
-
参数列表必须不一样
-
返回值类型可以相同也可以不同,返回值类型不同时,参数列表一定不能相同。
仅仅返回值不同不足以称之为方法的重载
实现理论
方法名称相同时,编译器会根据调用方法的参数个数,参数类型等逐一匹配来选择对应方法,如果匹配失败则爆红
递归!
递归就是一个方法中,自己调用自己
递归头:什么时候不调用自身的方法,如果没有头将陷入死循环
递归体:什么时候需要调用自身的方法
public static void main(String[] args){
demo01 demo=new demo01();
int result = demo.digui(5);
System.out.println(result);
}
//实现阶乘
public int digui(int a){
//递归头
if (a==1) {
return 1;
}else {
//递归体
return a*digui(a-1);
}
}
数组
定义:
数组是相同类型数据的长度固定的有序集合,每个数组元素可以通过其下标访问
数组可以看成对象它们都是引用类型,数组的元素可以看成成员变量
数组的申明创建
申明
数组类型 +数组名;
//dataType[] arrayName; dataType arrayName[];
int[] name; int name[];
创建
//new出数组
dataType[] arrayName=new dataType[arraySize];
int[] name=new int[4];//默认数组元素是0;
//数组索引从0开始
int[] name={1,2,3,4};
System.out.println(name[0]==1);//返回的true
//获取数组长度
name.length;
数组的初始化
//静态初始化
int[] name={1,2,3,4};//基本类型
Man[] mans={new man(1,1),new man(2,2)}//引用类型
//动态初始化
int[] name=new int[4];
name[0]=1;
name[1]=2;
name[2]=3;
name[3]=4;
数组和对象的内存分析
堆: 存放new的对象和数组,可以被所有线程共享,不会存放别的对象引用 栈:存放基本变量类型(包含其具体的值),引用对象的变量(包含其在堆里的具体地址)。 方法区 :可以被所有线程共享,包含了所有的class和static变量
写个列子:数组创建时栈堆工作流程
如果把数组理解成对象:
对象实体本身创建在堆中,它的引用变量创建在栈中
这里的array是对象实体的引用变量,而并非对象实体本身
对象的引用变量可以理解为指针,它存放的是对象实体的引用
//执行int[] array=new int[3];可以拆成下列几步
//1.申明整型数组array,此时栈中出现了array数组,但堆还没被创建
int[] array=null;
//2.创建数组,堆中创建array数组,栈中的array指向堆中的array数组
array=new int[3];
//3,给数组元素赋值,完成后堆中数组元素将被赋值,栈中也会存在这些值
array[0]=1;
array[1]=2;
array[2]=3;
数组的使用
普通for循环
可以运用下标对数组进行精细的操作
for-each循环
不能运用下标,但可以很方便的打印数组
数组做方法入参
数组做方法的返回值
多维数组
多维数组可以看成是数组的数组,比如二维数组可以看成一个特殊的一维数组,其每个元素都是一个一维数组。
二维数组
int a[][]=new int[2][5]
//例子
int[4][2] array={{1,1},{2,2},{3,3},{4,4}}
//三维
int[4][2][2] array={{{1,1},{1,2}},{{2,1},{2,2}},{{3,1},{3,2}},{{4,1},{4,2}}}
array[0]=={{1,1},{1,2}};array[0][0][0]==1;
array[1]=={{2,1},{2,2}};
array[2]=={{3,1},{3,2}};
array[3]=={{4,1},{4,2}};
数组的实际应用
Arrays工具类
其所有方法都是static修饰,可以直接使用类名调用
直接打印数组:toString
给数组赋值:fill方法
int[] a={1,2,3,4};
Arrays.fill(a,0);//数组里面所有元素填充成0
[0,0,0,0]//打印结果
Arrays.fill(a,1,2,0);//填充[1,2)半开半闭区间的索引为0
[1,0,3,4]//打印结果
对数组排序:sort方法,默认升序
比较数组:equals
查找数组元素:binarySearch方法能对数组进行二分法查找
冒泡排序
这里就简单认识一下八大排序算法之一的冒泡排序,其他排序自己再去了解吧
冒泡排序相对简单,两层循环,外层冒泡轮数,里层依次比较
原始模版
public static int[] sort(int[] array){
int temp=0;
//外层循环,判断要执行多少次(内层循环执行完一次会得一个到内层的极值)
for(int i=0;i<array.length-1;i++){
//内层循环,由if决定排序方式,这里是后一个数比前一个数大则交换位置(故大的会排在前面)
for (int j=0;j<array.length-1-i;j++){
if (array[j+1]>array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
return array;
}
优化冒泡排序
这只是一种思路,不见得优化的了多少
public static int[] sort2(int[] array){
int temp=0;
//外层循环,判断要执行多少次(内层循环执行完一次会得一个到内层的极值)
for(int i=0;i<array.length-1;i++){
Boolean flag=false;
//内层循环,由if决定排序方式,这里是后一个数比前一个数大则交换位置(故大的会排在前面)
for (int j=0;j<array.length-1-i;j++){
if (array[j+1]>array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
flag=true;
}
//若经过多次内层循环使靠后索引的排序达到要求,即可直接退出外层循环,相当于省略了些步骤
if (flag!=true){
break;
}
}
}
return array;
}
稀疏数组
场景:五子棋游戏,以1为白棋,2为黑棋,0为空地,这样没有记录意义0就占用了很多内存
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
当一个数组中大部分元素为0,或者为同一数值时,可以用稀疏数组来保存该数组
处理思路
-
记录数组有几行几列,有多少不同的值
-
把具有不同值的元素和行列以及值记录在小规模数组中,从而缩小程序规模
如下
0 0 0 0 0 0 0 0
0 33 0 0 0 0 53 0
0 0 0 21 0 0 0 0
0 0 0 0 14 0 0 0
0 0 33 0 0 0 0 0
0 0 0 0 0 0 0 0
会被记录成
行(row)|列(col)|值(value)
[0] 6 | 5 | 5 //这里行列是整个行列(全是0不能忽略),值是不同数的个数
------------------------------
[1] 1 | 1 | 33 //这里行列是值在全部行列的位置(从0开始计算)
[2] 1 | 6 | 53
[3] 2 | 3 | 21
[4] 3 | 4 | 14
[5] 4 | 2 | 33
代码实现
转换稀疏数组以及还原
public class SparseArray {
public static void main(String[] args) {
// 1.模拟出来棋盘数据,使用二维数组
int num = 11;
int[][] array = new int[num][num];
array[1][2] = 1;
array[2][4] = 2;
// 打印棋盘查看效果
for (int[] row : array) {
for (int val : row) {
System.out.printf("%d\t", val);
}
System.out.println();
}
// 需要把如上的二维数组中有效数据压缩至稀疏数组中去
// 计算二维数组中有效数据
int sum = 0;
for (int i = 0; i < num; i++) {
for (int j = 0; j < num; j++) {
if (array[i][j] != 0) {
sum++;
}
}
}
// 定义稀疏数组
int[][] sparseArray = new int[sum + 1][3];
// 行
sparseArray[0][0] = 11;
// 列
sparseArray[0][1] = 11;
// 有效数据个数
sparseArray[0][2] = sum;
// 把有效数据存放至稀疏数组中去
int count = 0;
// 行的索引
for (int i = 0; i < num; i++) {
// 列的索引
for (int j = 0; j < num; j++) {
// 判断是否是有效数据
if (array[i][j] != 0) {
count++;
sparseArray[count][0] = i;
sparseArray[count][1] = j;
sparseArray[count][2] = array[i][j];
}
}
}
// 打印稀疏数组
for (int[] ints : sparseArray) {
// System.out.printf("%d,%d,%d\t", ints[0], ints[1], ints[2]);
System.out.println(ints[0] + " " + ints[1] + " " + ints[2]);
}
// 把稀疏数组转原始二维数组(面试题)
int[][] oldArray = new int[sparseArray[0][0]][sparseArray[0][1]];
for (int i = 1; i <= count; i++) {
oldArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
System.out.println("========================================");
// 原始二维数组棋盘
for (int[] row : oldArray) {
for (int val : row) {
System.out.printf("%d\t", val);
}
System.out.println();
}
}
}