1.方法
java方法是语句的集合,它们在一起执行一个功能
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
设计方法的原则:一个方法只完成1个功能,这样利于我们后期扩展。
方法的定义
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
package com.kuang.method;
public class Demo01 {
//main方法
public static void main(String[] args) {
int sum = add(1,2);
System.out.println(sum);
}
//加法
public static int add(int a,int b){
return a + b;
}
}
注意:方法返回值通过return语句实现,如果没有返回值,返回值类型设置为void,可以省略return。
方法调用使用:“类名.”
package com.kuang.method;
public class Demo02 {
public static void main(String[] args) {
int a = max(10,10);
System.out.println(a);
System.out.println("===========");
//使用类名.的方式调用
int b = Demo02.max(26,78);
System.out.println(b);//78
System.out.println("===========");
System.out.println(Demo02.max(10,20));//20
}
//比大小
public static int max(int num1,int num2){
int result;
if (num1 == num2){
System.out.println("num1 == num2");
return 0;//终止方法
}
if (num1 > num2){
result = num1;
}else {
result = num2;
}
return result;
}
}
2.方法重载 overlord
重载就是在一个类中,有相同的函数名称,但形参不同的函数
方法重载的规则:
- 在同一个类中且方法名必须相同
- 参数列表必须不同(参数个数不同算不同,参数类型不同算不同,参数顺序不同也算不同)
//例:方法重载简化输出语句
public class s{
public static void p(){
System.out.println();
}
public static void p(byte b){ //输出byte类型
System.out.println(b);
}
public static void p(short s){ //输出short类型
System.out.println(s);
}
public static void p(int i){ //输出int类型
System.out.println(i);
}
public static void p(long l){ //输出long类型
System.out.println(l);
}
public static void p(float f){ //输出float类型
System.out.println(f);
}
public static void p(double d){ //输出double类型
System.out.println(d);
}
public static void p(Boolean b){ //输出boolean类型
System.out.println(b);
}
public static void p(char c){ //输出char类型
System.out.println(c);
}
public static void p(String s){ //输出String类型
System.out.println(s);
}
}
/*实现结果:
System.out.println(“Hello World!”)
s.p(“Hello World!”)
方法重载的目的:功能类似的方法使用同一名字,更容易记住,因此调用起来更简单。
*/
3.可变参数(了解)
JDK1.5开始,java支持传递同类型的可变参数给一个方法
在方法声明中,在指定参数类型后加上一个省略号(...)
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须在它之前声明。
package com.kuang.method;
public class Demo04 {
public static void main(String[] args) {
Demo04 demo04 = new Demo04();
demo04.test(1,2,3,4,5);
}
// public void test(int...i,int x)会报错
///public void test(int a,int...i)可以
public void test(int...i){
System.out.println(i[0]);
}
}
4.递归
递归就是方法自身调用自身
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
package com.kuang.method;
public class Demo05 {
public static void main(String[] args) {
System.out.println(f(5));//120
}
//阶乘
//1! 1
//2! 2*1
//5! 5*4*3*2*1
public static int f(int n){
if (n == 1) {//结束条件
return 1;
}else {
return n * f(n-1);
//若传递2:2 2 * f(1)
//若传递3:3 3 * f((2)
}
}
}
使用递归计算1~N的和
Public static void main(String[] args){
Int revalue = sum(3);
System.out.println(reValue);
}
Public static int sum(int n){
if(n == 1){//结束条件
return 1;
}
return n + sum(n - 1);
}
注意:使用递归的时候,必须添加结束条件,否则会发生栈内存溢出(StackOverflowError)
原因:一直压栈,没有弹栈,栈内存不够
在实际开发中遇到递归导致的栈内存溢出怎么办?
- 检查结束条件是否正确
- 如果正确,可以调整JVM的栈内存大小(java -X)
5.数组
- 数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
- 数组中的元素内存地址是连续的
- 数组中首元素的内存地址作为整个数组对象的内存地址
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[] arrayRefVar;//首选的方法
//或
dataType arrayRefVar[];//效果相同,但不是首选方法
//java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
数组中每一个元素都有下标,从0开始,以1递增,最后一个元素的下标是length-1
获取数组长度:arrays.length
package com.kuang.array;
public class ArrayDemo01 {
public static void main(String[] args) {
int[] nums;//1.声明一个数组
//int nums2[];早期java偏向c和c++的风格
//2.创建一个数组
nums = new int[10];//这里面可以存放10个int类型的数字
//3.给数组元素赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
System.out.println(nums[0]);//1
System.out.println(nums[1]);//2
System.out.println(nums[2]);//3
System.out.println(nums[3]);//0,没赋值会是默认的值
//计算所有元素的和
int sum = 0;
//获取数组长度:arrays.length
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
System.out.println("总和为:" + sum);//总和为:6
}
}
//字符串数组
//字符串是引用类型,因此我们定义一个字符串数组:
String[] names = {
“ABC”,”XYZ”,”Zoo”
};
数组的优点与缺点
优点:查询/查找/检索某个下标上的元素是效率极高
原因:
- 每一个元素的内存地址在空间存储上是连续的
- 每一个数据类型都相同,所以占用空间大小一样
- 知道第一个元素内存地址,知道每个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标元素的内存地址,直接通过内存地址定位元素
缺点:随机增删效率较低
原因:
- 为了保证数组中每个元素的内存地址是连续的,所以在数组上随机删除或增加元素的时候,效率极低,因为随机增删元素会涉及到后面元素向前或向后位移的操作
- 数组不能存储大数据量,因为很难在内存空间找到一块特别大的连续的内存空间
Java内存分析
- 堆:存放new的对象和数组,可以被所有的线程共享,不会存放别的对象引用
- 栈:存放基本变量类型(包含这个基本类型的具体数值)、引用对象的变量(存放这个引用再堆里面的具体地址)
- 方法区:可以被所有的线程共享,包含了所有class和static变量
数组的三种初始化:静态初始化、动态初始化、默认初始化
package com.kuang.array;
public class ArrayDemo02 {
public static void main(String[] args) {
//静态初始化:创建 + 赋值
int[] a = {1,2,3,4,5,6,7,8};
System.out.println(a[0]);//1
//动态初始化:包含默认初始化
int[] b = new int[10];//需手动赋值,不然是默认值
b[0] = 10;//赋值
System.out.println(b[0]);//10
System.out.println(b[1]);//0
}
}
//声明一个int类型的数组,使用静态初始化方式
int[] a = {1,100,10,20,55,689};
//所有数组对象都有length属性
System.out.println("数组中元素的个数:" + a1.length);//6
//数组中每一个元素都有下标
//通过下标对数组中的元素进行存和取
//取(读)
System.out.println("第一个元素=" + a[0]);//1
System.out.println("最后的元素=" + a[5]);//689
System.out.println("最后的元素=" + a[a.length - 1]);//689
//存(改),把第一个元素修改为111
a[0] = 111;
//把最后一个元素修改为0
a[a.length - 1] = 0;
System.out.println("第一个元素=" + a[0]);//111
System.out.println("最后的个元素=" + a[5]);//0
数组的四个基本特点
- 其长度是确定的,数组一旦被创建,大小就是不可以改变的
- 其元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型
- 数组属于引用类型,也可以看成是对象。数组中的每个元素相当于该对象的成员变量。数组对象本身是存放在堆中的。
数组边界
下标的合法区间:[0,length - 1],如果越界就会报错
ArrayIndexOutOfBoundsException:数组下标越界异常!
数组的使用
普通for循环与For-Each循环
普通for循环遍历
package com.kuang.array;
public class ArrayDemo03 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
//打印全部的数组元素
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
System.out.println("==============");
//计算所有元素的和
int sum = 0;
for (int i = 0; i < arrays.length; i++) {
sum += arrays[i];
}
System.out.println("sum = " + sum);
//查找最大元素
int max = arrays[0];
for (int i = 1; i < arrays.length; i++) {
if (arrays[i] > max){
max = arrays[i];
}
}
System.out.println("max = " + max);
}
}
foreach遍历
package com.kuang.array;
public class ArrayDemo04 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
//foreach遍历,没有下标
for (int array: arrays) {
System.out.println(array);
}
}
}
多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
二维数组
int a[][] = new int[2][5];
//解析:以上二维数组a可以看成是一个两行五列的数组
package com.kuang.array;
public class ArrayDemo05 {
public static void main(String[] args) {
//[3][2]:3行2列
/*
1,2 a[0]
3,4 a[1]
5,6 a[2]
*/
int[][] a = {{1,2},{3,4},{5,6}};
System.out.println(a[0][0]);//1
System.out.println(a[0][1]);//2
System.out.println(a[1][0]);//3
System.out.println("==========");
System.out.println(a.length);//3:表示3行
System.out.println(a[0].length);//2:表示2列
System.out.println("==========");
//二维数组遍历
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.println(a[i][j]);
}
}
}
}
一维数组扩容
扩容是先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中
注意:数组扩容效率极低
public class ArrayTest08 {
public static void main(String[] args) {
//java当中的拷贝方法
//System.arraycopy(5个参数);
int[] src = {1,11,22,3,4};//拷贝源
int[] dest = new int[20];//拷贝目标,动态初始化一个长度为20的数组
//调用arraycopy方法
System.out.println(src,srcPost:1(拷贝源起始位置),dest,destPos:3(拷贝到的位置),length:2(拷贝长度));
//遍历数组
for(int i = 0; i < dest.lentgh; i++){
System.out.rptinln(dest[i]);//0 0 0 11 22…0
}
//拷贝源
String[] strs = {"hello","world!","java","oracle","mysql","jdbc"};
//拷贝目标
String[] newStrs = new String[20];
System.arraycopy(strs,0, newStrs, 0, strs.length);
for (int i = 0; i < newStrs.length; i++) {
System.out.println(newStrs[i]);
}
}
}
6.Arrays类
数组的工具类java.util.Arrays
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用
具有以下常用功能:
- 给数组赋值:通过fill方法
- 对数组排序:通过sort方法,按升序
- 比较数组:通过equals方法比较数组中元素值是否相等
- 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作
package com.kuang.array;
import java.util.Arrays;
public class ArrayDemo06 {
public static void main(String[] args) {
int[] a = {1,2,3,4,9090,31231,543,21,3,23};
System.out.println(a);//[I@154617c
//打印数组元素:Arrays.toString
System.out.println(Arrays.toString(a));//[1, 2, 3, 4, 9090, 31231, 543, 21, 3, 23]
Arrays.sort(a);//对数组进行排序:升序
System.out.println(Arrays.toString(a));//[1, 2, 3, 3, 4, 21, 23, 543, 9090, 31231]
Arrays.fill(a,0);//数组填充
System.out.println(Arrays.toString(a));//[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Arrays.fill(a,2,4,1);//让下标为2跟4之间的元素填充为1
System.out.println(Arrays.toString(a));//[0, 0, 1, 1, 0, 0, 0, 0, 0, 0]
}
}
7.冒泡排序
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序
package com.kuang.array;
import java.util.Arrays;
//冒泡排序
/*
1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换它们的位置
2.每一次比较,都会产生一个最大或者最小的数字
3.下一轮则可以少一次排序
4.依次循环,直到结束
*/
public class ArrayDemo07 {
public static void main(String[] args) {
int[] a = {6,4,2,1,26,78};
int[] sort = sort(a);
System.out.println(Arrays.toString(a));//[1, 2, 4, 6, 26, 78]
}
public static int[] sort(int[] array){
//临时变量
int temp = 0;
//外层循环,判断我们这个要走多少次
for (int i = 0; i < array.length - 1; i++) {
//内层循环,比较判断两个数,如果第一个数比第二个数大则交换位置
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;
}
}