方法(函数)
/*
* 在Java中本质上是不区分函数和方法的,因为Java是有面向过程和面向对象存在,
* 但是因为Java本身就是一门面向对象的语言,所以应该叫方法(个人建议)
* 方法:一段特定功能的代码
* DRY原则:Don't Repeat Youself! 有效代码:核心逻辑 240/day
*
* 语法:访问权限修饰符 [其他修饰符] 返回值类型 方法名(形参列表){ 方法体 ; [return;] }
* 1.访问权限修饰符:权限问题(谁可以访问) public:公有(任何人都可访问) 访问权限修饰符 若不写就是默认
* 2.其他修饰符:使用了中括号标注(可以没有) static:静态的
* 3.返回值类型:1.值类型 2.引用类型 3.void 决定着 return 是否书写
* 4.方法名:遵守标识符命名规则,不准使用拼音,不宜过长
* 5.形参列表(参数列表):参数的类型+参数个数+参数的顺序
* 6.{}方法代码块,主要方法的逻辑都写在这里
* 7.return:可以结束一个方法并带回一个返回值,基本是最后一行,除非逻辑需要可以写在分支或循环中
* 方法运行中一旦出现return,方法即刻结束,return后的代码都不会执行,return一次只带回一个值
*
* 方法签名(必须唯一) = 方法名 + 方法参数列表
* 同一个类中是不能出现两个相同的方法签名的
*
* 方法需要定义在类的内部或接口的内部,所有的方法都是平级的,不能在方法中再定义方法,
* 方法定义的顺序无影响,主要看调用顺序
*
* 方法重载:面向对象中多态的一个概念
* 方法名相同,参数列表不同,减少方法个数
* Java自带的推断机制,当调用方法时,根据参数自动推断最合适的方法
* 重载的问题:在定义重载时,参数类型尽量一致
*
* 递归方法:方法自己调用自己 [从前有座山.......]
* 一个方法体内调用它自身,这样的方式称为递归(方法递归包含了一个隐式的循环)
* 一定要有一个结束的点(一个出口)
*/
- 方法重载:
public class MethodOverload {
//求出两个整数的和
public static int getSum(int a,int b) {
return a+b;
}
//求两个小数的和
public static double getSum(double a,double b) {
return a+b;
}
public static void main(String[] args) {
int sum = getSum(1,2);
System.out.println(sum);
double sum1 = getSum(1.1,1.2);
System.out.println(sum1);
}
}
- 递归练习:
/*
* 能用递归解决的问题,基本上都能用循环,复杂的递归循环不能代替
* 递归能不写就不写,耗性能的操作,但是递归绝对比循环快
*
* 有6个人,6说5比他大3岁,5说4比他大3岁,4说3比他大3岁
* 3说2比他大3岁,2说1比他大3岁,1说13岁,问第六个人多大
*/
public class Lisp {
public int yearLisp(int n) {
if(n == 1){
return 13;
}else{
return 3 + yearLisp(n-1);
}
}
public static void main(String[] args) {
Lisp lisp = new Lisp();
System.out.println(lisp.yearLisp(6));
}
}
数组
/*
* 数组:引用数据类型,在堆中而不是在栈中
* 一个定长容器,一次性存储很多相同数据类型的值方便操作
* 数组和集合的区别:数组是定长
* 数组既可以存基本数据类型,也可以存引用类型
*
* 数组中元素的数据类型:int等
* 数组的数据类型:int []
*
* 堆:归程序员管,内容由GC回收,
*/
- 数组的四种创建方式:
//1.标准创建方式
//数据类型[] 数据名 = new 数据类型[数组的大小(长度)]
int[] arr1 = new int[10];
//2.先声明再赋值
//数组中元素的类型 [] 数组名;
//数组名 = new 数组中元素的类型 [数组的大小(长度)];
//ps:这样写,数组一定要赋值后才可以使用,不能直接使用否则空指针null
int[] arr2;
arr2 = new int[10];
//3.声明的同时指定初始化值
//数组中元素的类型[] 数组名 = new 数组中元素的类型[]{值};
//ps:根据大括号中具体的值的个数,来决定数组的长度
int[] arr3 = new int[]{1,2,3,4,5};
//4.是第三种的简化版本
int[] arr4 = {1,2,3,4,5};
- 数组的基本操作:
/*
* 数组的赋值(静态赋值和动态赋值)
* 静态赋值:创建数组的同时并赋值
* 例子: int[] arr4 = {1,2,3,4,5};
* 动态赋值:数组每个元素的值都是通过某些方式计算出来,或者是通过控制台赋值的
* 例如: int[] arr5 = new int[3];
* arr5[0] = (int)(Math.random*100); 或者 arr5[0] = input.nextInt();
*/
//下标:数组中元素所标注的位置 从0 开始 到 数组长度-1 结束
int[] arr4 = {1,2,3,4,5};
//获取第3位的值
int num = arr4[3]; //取值
System.out.println(num);
//修改第3位的值
arr4[3] = 100;
//arr4.length数组长度
System.out.println(arr4[arr4.length-1]);
//ArrayIndexOutOfBoundsException 数组下标越界异常
//下标不能是负数也不能超过数组的长度-1
System.out.println(arr4[5]);
- 通过循环遍历数组:
//创建一个数组 数组的长度是10,随机存1-100之间的数字
int[] arr = new int[10];
//普通for循环
for(int i = 0; i<arr.length ; i++) {
arr[i] = (int)(Math.random()*100+1);
}
for(int i = 0; i<arr.length ; i++) {
System.out.println(arr[i]);
}
System.out.println("-------华丽的分割线--------");
//增强for循环
/*
* 反编译原码:
* int ai[];
* int l = (ai = arr).length;
* for (int j = 0; j < l; j++){
* int num = ai[j];
* num = 0;
* System.out.println(num);
* }
*/
for(int num:arr){
num = 0;
System.out.println(num);
}
System.out.println("-------华丽的分割线--------");
for(int num:arr){
System.out.println(num);
}
总结:
同:两个循环都可以遍历数组并打印
不同:普通for循环不仅可以打印还可以赋值,增强for循环只能取值,但不能赋值
- 数组的排序:
/*
* 常用的数组排序:冒泡,选择,插入,快排,归并,堆排等等
* 排序没有说明之前,默认都是升序,即从小到大,将冒泡或选择修改为降序 只需要将if判断中的 > 修改为 < 即可
*/
/*
* 冒泡:对未排序的各个元素从头到尾依次比较相邻的两个元素
* 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
* 2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
* 3.针对所有的元素重复以上的步骤,除了最后一个。
* 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
*/
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = new int[10];
//给数组进行赋值
for(int i = 0; i < arr.length ; i++){
arr[i] = (int) (Math.random()*100);
}
System.out.println("排序之前数组的值:");
System.out.println(Arrays.toString(arr));
System.out.println("排序之后数组的值:");
for(int i = 0; i < arr.length ; i++){
/*
* -1 是为了不让数组越界
* -i是因为随着比较的次数逐渐的增多,有序的个数也在增多
* 所以-i可以减少排序的个数
*/
for(int j = 0; j < arr.length-1-i ; j++){
if(arr[j] > arr[j+1]){
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
System.out.print("第"+(i+1)+"次排序的结果:\t");
//打印第 i+1 次排序结果
for(int m = 0; m<arr.length;m++) {
System.out.print(arr[m]+"\t");
}
System.out.println();
}
System.out.println(Arrays.toString(arr));
}
}
/*
* 选择排序:需要选择某个索引位置的元素,然后和后面的元素依次比较,若大就交换,
* 经过一轮之后可以找到数组中最小的值,剩余元素比较完后完成即可。
*/
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int[] arr = new int[10];
//给数组进行赋值
for(int i = 0; i < arr.length ; i++){
arr[i] = (int) (Math.random()*100);
}
System.out.println("排序之前数组的值:");
System.out.println(Arrays.toString(arr));
System.out.println("排序之后数组的值:");
for(int i = 0; i < arr.length ; i++){
for(int j = i+1; j < arr.length ; j++){
if(arr[i] > arr[j]){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
System.out.print("第"+(i+1)+"次排序的结果:\t");
//打印第 i+1 次排序结果
for(int m = 0; m<arr.length;m++) {
System.out.print(arr[m]+"\t");
}
System.out.println();
}
System.out.println(Arrays.toString(arr));
}
}
- 数组中数的查找:
/*
* 线性查找
*/
import java.util.Arrays;
import java.util.Scanner;
public class LineSearch {
/**
* 线性查找
* @param num 要查找的数
* @param arr 要查找的数组
* @return 正数 证明找到了即下标 负数 没找到
*/
public static int FindNumberForArray(int num,int[] arr) {
for(int i = 0;i<arr.length;i++) {
if(num == arr[i]) {
return i;
}
}
return -1;
}
public static void main(String[] args) {
//线性查找
int[] arr = new int[10];
//给数组进行赋值
for(int i= 0; i<arr.length;i++) {
arr[i] = (int)(Math.random()*100);
}
System.out.print("数组的元素有:");
System.out.println(Arrays.toString(arr));
Scanner scanner = new Scanner(System.in);
System.out.println("输入要查找的值:");
int num = scanner.nextInt();
int index = FindNumberForArray(num, arr);
if(index > 0) {
System.out.println("存在在数组中下标:"+index);
}else {
System.out.println("不存在");
}
}
}
/*
* 二分查找也称折半查找,它是一种效率较高的查找方法。
* 但是,折半查找要求线性表必须采用顺序存储结构
*
* 将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;
* 如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.
*/
import java.util.Arrays;
import java.util.Scanner;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = new int[10];
//给数组进行赋值
for(int i= 0; i<arr.length;i++) {
arr[i] = (int)(Math.random()*100);
}
System.out.print("数组的元素有:");
System.out.println(Arrays.toString(arr));
Scanner scanner = new Scanner(System.in);
System.out.println("输入要查找的值:");
int num = scanner.nextInt();
//数组必须有序
sortArray(arr);
//查找
int index = BinarySearch(num, arr);
if(index > 0) {
System.out.println("存在在数组中下标:"+index);
}else {
System.out.println("不存在");
}
}
/**
* 选择排序 (升序)
* @param arr 整型数组
*/
public static void sortArray(int[] arr) {
for(int i = 0; i<arr.length;i++) {
for(int j = i+1;j<arr.length;j++) {
if(arr[i] > arr[j]) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}
public static int BinarySearch(int num, int[] arr) {
System.out.println(Arrays.toString(arr));
/**
* 二分查找理论:
* 需要在数组中定义beginIndex和endIndex
* 通过 (beginIndex+endIndex)/2 --> middleIndex中间值
* 通过要查找的数 和中间值即下标位置的值进行比较
* 因为已经排序,所以数据是从小到大,若查找值大于中间值对应的数值
* 移动beginIdex =middleIndex+1,重新计算中间值继续比较
* 若查找的值小于中间值的数值,
* 移动endIndex = middleInex-1,重新计算中间值继续比较
* 若出现beginInex > endIndex 没有找到返回-1 否则即找到返回下标
* ps:找到值的下标就是中间值
*/
int begIndex = 0;//开始值
int endIndex = arr.length-1;//结束值
int middleIndex = (begIndex+endIndex)/2;
//比较
while(true) {
//缩小范围进行比较
if(num > arr[middleIndex]) {
//修改开始值
begIndex = middleIndex+1;
}else if(num < arr[middleIndex]) {
//修改结束值
endIndex = middleIndex-1;
}else {
return middleIndex; //找到了
}
//重新计算中间值
middleIndex = (begIndex+endIndex)/2;
//没有找到即 开始> 结束
if(begIndex > endIndex) {
return -1;
}
}
}
}
- 传值和传址:
传值:
传址:
总结:
1.java中的方法无论是传值还是传址,都是将值或地址进行复制传递,但是这个复制完全是不一样的
2.值相当于是副本,所有对副本的修改都不会影响原有的值
3.地址的传递也是拷贝过去,但是因为或取的是同一个地址,所有操作的是用一个空间,所以任何一方的修改都影响彼此
- 可变参数(JDK1.5):
调用含有可变参数的方法时,编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数
/*
* 可变参数:在设计方法时,主要是应对参数的[个数不定],此时可以使用可变参数
* 1.可变参数必须放到所有形参的最后
* 2.一个方法中最多只能有一个可变参数
* 3.既然是可变参数,那么就意味着可以传参(多参数使用,隔开),也可以不传参
* 4.方法使用可变参数相当于使用了一维数组
* 5.可变参数写法 --> 数据类型...(只能是三个点)变量
*/
public class VariaParameters {
static void inputArray(int... arr){
for(int num:arr){
System.out.print(num+"\t");
}
System.out.println();
}
public static void main(String[] args) {
inputArray();
System.out.println("------------------------------");
inputArray(1,2,3,4,5);
System.out.println("------------------------------");
int[] nums = {7,8,9};
inputArray(nums);
}
}
运行结果:
- Arrays工具类:
/*
* Arrays是工具类,
* 负责对数组进行排序、查找、填充、复制等操作
*/
import java.util.Arrays;
public class ArraysUtil {
public static void main(String[] args) {
int[] arr = new int[10];
for(int i = 0; i<arr.length; i++){
arr[i] = (int) (Math.random()*100);
}
//toString --> 返回值是一个字符串
String str = Arrays.toString(arr);
System.out.println(str);
//sort 排序 默认是升序(需要学到比较接口时才能实现自定义排序)
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
//使用二分查找(必须排序)
/*
* 第一参数:要查找的数组
* 第二参数:要查找的数
* 返回值是一个int类型,找到了即下标,找不到是 负数
*/
int index = Arrays.binarySearch(arr, 100);
System.out.println(index);
//复制数组
/*
* 浅拷贝:相当于将原有数组的内容和地址复制给新的数组,地址也是一样的
* int[] arr1 = {1,2};
* int[] arr2 = arr1;
*
* 深拷贝:相当于将原有数组中的内容复制给新的数组,但是地址不一样
* int[] arr1 = {1,2};
* int[] arr2 = new int[2];
* for(int i=0; i<arr1.length;i++){
* arr2[i] = arr1[i];
* }
*
* 第一参数 是原有数组
* 第二参数 是新数组的长度
* ps:不能是 负数 ,若长度 <= 原有数组长度 可以复制其原有数组中的内容
* 超过原有数组的长度部分,以默认值占位
*/
int[] newArr = Arrays.copyOf(arr, 20);//深拷贝
//int[] arrCopy = arr.clone();//深拷贝(Object的clone)
System.out.println("打印新数组的长度:"+newArr.length);
System.out.println("打印新数组中的内容:"+Arrays.toString(newArr));
//copyOfRange(原有数组,开始的位置,结束的位置) 深拷贝
//复制一段数组中的内容 最后一个参数是不包含的,即[)
//开始的位置和结束的位置都是下标,结束的位置处的索引可以越界
/*
* equals 判断两个数组是否相等
* equals这个方法是Object所提供的,用来判断引用类型是否相等
* 引用类型严禁使用 == 来判断是否相等
*/
int a = 1;
int b = 1;
System.out.println(a == b);
int[] a1 = {1,2,3,4,5};
int[] a2 = {1,2,3,4,5};
//此时若调用 == 就相当于比较了a1和a2的地址
System.out.println(a1 == a2);
//若要判断是否相等
System.out.println(Arrays.equals(a1, a2));
}
}
- 二维数组:
public class TwoArrays {
public static void main(String[] args) {
//二维数组(画图用)
int[][] arr = new int[3][5];
int[][] arr1 = {
{0,0,1,0,0},
{0,1,0,1,0},
{1,0,0,0,1},
{0,1,0,1,0},
{0,0,1,0,0}
};
//遍历数组,双层for循环
//相当于二维数组中有多少个一维数组
for(int i=0; i<arr1.length; i++){
for(int j=0; j<arr1[i].length; j++){
if(arr1[i][j] == 1){
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println();
}
}
}
运行结果: