1.方法定义
方法(Method)、函数(Function)其实就是指一个特定的功能操作
如果方法使用了static修饰,此时我们使用方法所在的类的名称,方法名(参数)
如果方法没有使用static修饰,此时我们将使用方法所在类的对象来调用
static表示方法属于类,直接使用类名调用即可
2.方法中的术语
修饰符:public.static等;static修饰的方法属于类,直接使用类名调用即可
返回值类型:方法其实是在完成一个功能,该功能操作完毕之后,是否需要给调用者返回一个结果.如果不需要给调用者返回结果,此时关键字void来声明,表示没有返回值;
方法名称:遵循标识符的规范,使用动词表示,首字母小写,若是多个单词组成,使用驼峰表示法;
形式参数:方法圆括号中的变量,仅仅只是占位而已,参数的名称其实无所谓,形式参数可以有多个;
参数列表:参数列表==参数的类型+参数的个数+参数的顺序;
方法签名:方法签名==方法名称+方法参数列表;(在同一类中,方法签名是唯一的.否则编译报错)
方法体:方法中{}中的代码,表示具体完成该功能的代码;
返回值:在方法内部,使用return关键字;(功能1:给调用者返回一个结果值,此时该方法不能使用void修饰.功能2:结束当前方法.)
3.方法的重载(overload)
重载方法的定义是在同一个类中,某方法允许存在一个以上的同名方法,只要它们的参数列表不同即可
方法重载的作用:屏蔽了统一供能的方法由于参数列表不同所造成的方法名称不同
方法重载判断原则:“两同一不同”
两同:同类中,方法名相同
一不同:方法参数列表不同(参数类型、参数个数、参数顺序)
注意:方法重载和方法的返回值类型无关,只是一般要求返回值类型一致
public class MethodDemo {
// 求两个整数之和
static int getSum (int a, int b) {
return a + b;
}
// 求两个小数之和
static double getSum (double a, double b) {
return a + b;
}
public static void main(String[] args) {
// 实际这个打印方法也是重载
System.out.println(MethodDemo.getSum(1, 3));;
System.out.println(MethodDemo.getSum(1.3, 2.4));;
}
}
4.JVM内存模型
JWM内存划分,人为的根据不同内存空间的存储特点以及存储的数据:
图片.png<strong>程序计数器</strong>:当前线程所执行的字节码的行号指示器.
<strong>本地方法栈</strong>:为虚拟机使用的native方法服务.
<strong>java虚拟机栈</strong>:描述java方法执行的内存模型,每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息.每一个方法,创建一个栈帧,栈帧存放了当前方法的数据信息.(局部变量),当方法调用完毕,该方法的栈帧就被销毁了.
<strong>Java堆</strong>:被所有线程共享的一块内存区域,在虚拟机启动时创建.所有的对象实例以及数组都要在堆上分配(使用new关键字,就表示在堆中开辟一块新的存储空间).
<strong>方法区</strong>:线程共享的内存区域,存储已被虚拟机加载的类信息,常量,静态常量即时编译器编译后的代码数据等(这个区域的内存回收目标主要针对常量池的回收和对类型的卸载).
<strong>GC(Garbage Collection)</strong>:垃圾回收器.
java的自动垃圾回收机制:简单理解为.程序员就不需要手动的去控制内存的释放.当JVM发觉内存资源紧张的时候,就会自动地去清理无用对象(没有被引用到的对象)所占用的内存空间.
5.数组
基本数据类型:byte,short,int,long,float,double,char,boolean
引用数据类型:类,接口,数组
数组的定义:
方式1:数组的元素类型[] 数组名;int[] ages; (推荐使用这种写法,可以把int[]看成是一种数据类型,int类型的数组类型)
方式2:数组元素的类型 数组名[];int ages[];
数组必须先初始化,才能使用,因为初始化表示在内存中分配空间
6.数组的静态初始化和内存分析
JAVA中数组必先初始化才能使用,所谓初始化就是给数组元素分配内存,并为每个元素赋初始值.
初始化数组的两种方式:静态初始化和动态初始化;
注意:无论以哪种方式初始化数组,一旦初始化完成,数组的长度就固定了,不能改变,除非重新初始化.也就是说数组是定长的.
数组的静态初始化操作
特点:由我们自己来为每一个数组元素设置初始化值,而数组的长度由系统决定.
语法:数组元素类型[] 数组名= new 数组元素类型[]{}(元素1,元素2,元素3......);
举例:
int [] nums = new int[]{1,3,5,7,9};
简单写法:必须声明之后立刻初始化,不能先声明后初始化
int [] nums = {1,3,5,7,9};
new关键字:在堆空间开辟一块内存区域,用来存储数据.
nums引用于堆空间中内存地址为0x1234这块区域.
我们表面上操作nums,其实底层操作是0x1234这块区域;
int[] nums=new int[]{1,3,5,7,9};
System.out.println(nums.length);
当在堆中重新开辟一个新空间如0x3456,赋值给nums,那么在栈中,nums的引用就回复改之前的0x1234变成0x3456,堆中0x1234空间就变成了垃圾,等待垃圾回收机制释放。
nums = new int[]{2,4,8};
System.out.println(nums.length);
如果要想让现在的引用0x3456也变成垃圾,直接将nums = null,null表示没有引用任何内存空间。若堆中的内存空间没有被引用的时候就变成了垃圾,等待垃圾回收器的回收
存储展示.png
7.操作数组常见异常
NullPointerException:空指针异常(空引用).
当数组还未进行初始化,就直接操作数组.
String[ ] bs = null;
System.out.println(bs.length)
ArraylndexOutOfBoundsException:数组的索引越界异常
8.main方法的数组参数
public class ArrayDemo {
public static void main(String[] args) {
}
}
main方法是static修饰的,说明直接使用ArrayDemo类调用即可。在底层JVM底层通过ArrayDemo.main(new String[]{})运行
main方法的String数组参数,其实是暴露给程序运行者的,用于给程序传递一个数据信息。
9.增强for循环foreach
在使用循环迭代数组的时候,往往不关心迭代变量(数组的索引),这时候可以使用foreach,通过反编译工具查看字节码,发现foreach其实在底层还是通过for循环+索引来操作数组的,我们把增强for循环称之为编译器的新特性(而不是底层的),就是一个语法糖(让开发者写更少、更简单的代码实现相同的功能)
10.冒泡排序:Bubble Sort
基本思路:对未排序的各元素从头到尾依次比较相邻的两个元素的大小,若大于则交换位置,经过第一轮比较排序后得到最大值,然后使用相同的方法把剩下的元素逐个比较即可。
可以看出若有N个元素,那么一共要进行N-1轮比较,第M轮要进行N-M次比较
public class MyClass {
public static void main(String[] args) {
// 冒泡排序
int[] array = {2, 9, 6, 7, 4, 1};
printArray(array);
bubbleSort(array);
printArray(array);
}
static void bubbleSort(int[] arr) {
for (int i = 1; i <= arr.length-1; i++) {
for (int j = 1; j <= arr.length - i; j++) {
if (arr[j - 1] > arr[j]) {
swap(arr, j-1, j);
}
}
}
}
// 打印数组
static void printArray(int[] arr) {
if (arr == null) {
System.out.println("null");
return;
}
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if (i != arr.length-1) {
System.out.print(", ");
}
}
System.out.println("]");
}
// 交换数组中的两个元素
static void swap(int[] arr, int index1, int index2) {
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
}
11.选择排序:Selection Sort
基本思路:选择某个索引位置的元素,然后和后面元素依次比较,若大于刚交换的位置,经过第一轮比较排序后可得出最小值,然后使用同样的方法把剩下的元素逐个比较即可。
可以看出选择排序,第一轮选出最小值,第二轮会选出第二小的值,直到最后。N个数要进行N-1轮,选择排序每一轮只进行一次交换,相对于冒泡排序效率高一些
// 该代码也不是最正确的选择排序
public class MyClass2 {
public static void main(String[] args) {
// 选择排序
int[] array = {2, 9, 6, 7, 4, 1};
printArray(array);
selectionSort(array);
printArray(array);
}
static void selectionSort(int[] arr) {
for (int i = 1; i <= arr.length-1; i++) {
for (int j = i; j <= arr.length - 1; j++) {
if (arr[i - 1] > arr[j]) {
swap(arr, i-1, j);
}
}
}
}
12.数组的搜索算法:从指定数组中去搜索某个元素的索引值是多少
方式一:线性搜索(从头到尾/从尾到头):indexOf()/lastIndexOf()
对于元素过多的数组,性能超低:有N个元素,循环次数=(N+1)/ 2
方式二:二分搜索法/二分查找法/折半查找
前提是数组元素必须有序
两者比较:当数据量很大适宜采用二分搜索法。采用二分搜索法查找时,数据需要时排序好的
public class MyClass3 {
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 二分法查找数组中的某个元素位置
int index = binarySearch(array, 8);
System.out.println(index);
}
static int binarySearch(int[] arr, int key) {
int low = 0; // 最低的索引;
int high = arr.length - 1; // 最大的索引
while (low <= high) {
int mid = (low + high) >> 1; // 操作二进制,相当于是除以2
// int mid = (low + high) / 2;
int midVal = arr[mid]; // 中间的元素,猜测的值
if (midVal > key) {
// 猜大了
high = mid - 1;
} else if(midVal < key) {
// 猜小了
low = mid + 1;
} else {
return mid;
}
}
return -1;
}
网友评论