Java 复习笔记 - 方法篇


在这里插入图片描述

一,方法的定义

在Java中,方法是一段独立的代码块,用于执行特定的任务或操作。方法可以接受输入参数并返回一个值,也可以不接受参数或不返回值。

方法由以下几个组成部分:

  1. 方法签名:方法的名称和参数列表的组合,用于唯一标识一个方法。方法签名包括方法名和参数类型,例如:methodName(parameterType1 parameter1, parameterType2 parameter2, ...)

  2. 方法体:方法体是方法中包含的代码块,实现了特定的功能或逻辑。方法体中的代码会按照顺序执行。

  3. 参数列表:方法可以接受零个或多个参数,参数是方法执行时传递给方法的值。每个参数包括参数类型和参数名称,用逗号分隔。

  4. 返回类型:方法可以返回一个值,也可以不返回值。返回类型指定了方法返回的数据类型。如果方法不返回任何值,则返回类型为 void

方法的定义格式如下:

修饰符 返回类型 方法名(参数列表) {
    // 方法体
}

其中:

  • 修饰符(可选):用于指定方法的可见性和访问权限,例如 publicprivate 等。
  • 返回类型:指定方法返回的数据类型,如果方法不返回任何值,则返回类型为 void
  • 方法名:方法的名称,用于在代码中调用方法。
  • 参数列表(可选):指定方法接受的参数类型和参数名称。
  • 方法体:方法中包含的代码块,实现具体的功能。

通过定义方法,可以将代码分解为更小的可维护和可重用的模块,提高代码的可读性和可维护性。

二,最简单的方法定义和调用

最简单的方法定义和调用可以按照以下步骤进行:

  1. 方法定义:首先,在类中定义一个方法。可以在类的任何位置定义方法,但通常放在类的最外层。
public class MyClass {
    
    
    // 方法定义
    public void myMethod() {
    
    
        // 方法体
        System.out.println("Hello, World!");
    }
}

上面的代码定义了一个名为 myMethod 的方法,它没有参数,返回类型为 void,在方法体中打印出 “Hello, World!”。

  1. 方法调用:在需要调用方法的地方,使用方法的名称后跟一对圆括号来调用方法。
public class MyClass {
    
    
    // 方法定义
    public void myMethod() {
    
    
        // 方法体
        System.out.println("Hello, World!");
    }

    public static void main(String[] args) {
    
    
        // 方法调用
        MyClass obj = new MyClass();
        obj.myMethod(); // 调用 myMethod 方法
    }
}

在上面的代码中,我们在 main 方法中创建了一个 MyClass 对象 obj,然后通过 obj.myMethod() 调用了 myMethod 方法。

运行上面的代码,输出结果为 “Hello, World!”。

三,带参数的方法定义和调用

带参数的方法定义和调用可以按照以下步骤进行:

  1. 方法定义:在方法的括号中定义参数。参数可以是任何合法的Java数据类型,可以有多个参数,参数之间用逗号分隔。
public class MyClass {
    
    
    // 带参数的方法定义
    public void myMethod(String name, int age) {
    
    
        // 方法体
        System.out.println("Hello, " + name + "! You are " + age + " years old.");
    }
}

上面的代码定义了一个名为 myMethod 的方法,它接受一个 String 类型的参数 name 和一个 int 类型的参数 age,在方法体中打印出带有参数信息的字符串。

  1. 方法调用:在调用方法时,传入相应的参数值。实际参数的数量、顺序和类型必须与方法定义中的形式参数相匹配。
public class MyClass {
    
    
    // 带参数的方法定义
    public void myMethod(String name, int age) {
    
    
        // 方法体
        System.out.println("Hello, " + name + "! You are " + age + " years old.");
    }

    public static void main(String[] args) {
    
    
        // 方法调用
        MyClass obj = new MyClass();
        obj.myMethod("Alice", 25); // 调用 myMethod 方法并传入参数值
    }
}

在上面的代码中,我们在 main 方法中创建了一个 MyClass 对象 obj,然后通过 obj.myMethod("Alice", 25) 调用了 myMethod 方法,并传入了一个 String 类型的参数 "Alice" 和一个 int 类型的参数 25

运行上面的代码,输出结果为 “Hello, Alice! You are 25 years old.”。

四,带返回值方法的定义和调用

带返回值的方法定义和调用可以按照以下步骤进行:

  1. 方法定义:在方法的返回类型前面加上返回类型。返回类型可以是任何合法的Java数据类型,包括基本数据类型和引用数据类型。
public class MyClass {
    
    
    // 带返回值的方法定义
    public int add(int a, int b) {
    
    
        // 方法体
        int sum = a + b;
        return sum;
    }
}

上面的代码定义了一个名为 add 的方法,它接受两个 int 类型的参数 ab,在方法体中计算它们的和,并将结果作为返回值。

  1. 方法调用:在调用方法时,可以使用一个变量来接收方法的返回值。
public class MyClass {
    
    
    // 带返回值的方法定义
    public int add(int a, int b) {
    
    
        // 方法体
        int sum = a + b;
        return sum;
    }

    public static void main(String[] args) {
    
    
        // 方法调用
        MyClass obj = new MyClass();
        int result = obj.add(5, 3); // 调用 add 方法并接收返回值
        System.out.println("The sum is: " + result);
    }
}

在上面的代码中,我们在 main 方法中创建了一个 MyClass 对象 obj,然后通过 obj.add(5, 3) 调用了 add 方法,并将返回值赋给了一个名为 resultint 类型变量。最后,我们使用 System.out.println 打印出结果。

运行上面的代码,输出结果为 “The sum is: 8”。

五,小结

总结一下Java方法的要点:

  1. 方法是一段可重复使用的代码块,用于完成特定的任务。
  2. 方法可以接受输入参数,并且可以有返回值。
  3. 方法定义包括方法的访问修饰符、返回类型、方法名称、参数列表和方法体。
  4. 方法的访问修饰符可以是 public、protected、private 或默认(不写修饰符)。
  5. 返回类型指定了方法执行后的返回值类型,可以是基本数据类型或引用数据类型。
  6. 方法名称应该具有描述性,符合命名规范,以便代码的可读性。
  7. 参数列表指定了方法接受的输入参数的类型和名称。
  8. 方法体是方法的具体实现,包含了执行的代码逻辑。
  9. 方法可以有返回语句来返回一个值,并且返回值的类型必须与方法的返回类型匹配。
  10. 方法可以被其他方法调用,通过方法名和参数列表来调用方法。
  11. 方法的调用可以在同一个类中进行,也可以在不同的类中进行,使用对象名或类名来调用方法。
  12. 方法可以被重载,即在同一个类中可以有多个同名但参数列表不同的方法。
  13. 方法可以被覆盖,即子类可以重写父类中的方法,以实现不同的功能。

以上是关于Java方法的一些要点,掌握了这些内容,就能够熟练地定义和使用方法来完成各种任务。

六,方法的重载

Java方法的重载是指在同一个类中,可以定义多个同名但参数列表不同的方法。方法的重载可以通过参数的个数、类型或顺序进行区分。

重载的方法具有以下特点:

  1. 方法名相同:重载的方法必须有相同的方法名。

  2. 参数列表不同:重载的方法的参数列表必须不同,可以是参数个数不同、参数类型不同或参数顺序不同。

  3. 返回类型可以相同也可以不同:重载的方法可以有相同的返回类型,也可以有不同的返回类型。

  4. 访问修饰符可以相同也可以不同:重载的方法可以有相同的访问修饰符,也可以有不同的访问修饰符。

  5. 重载的方法可以抛出相同或不同的异常:重载的方法可以声明相同的异常,也可以声明不同的异常。

重载的方法用于实现相似功能但参数不同的情况,提高代码的复用性和可读性。在调用重载的方法时,编译器会根据实际传入的参数类型来确定调用哪个方法。如果找不到匹配的方法,则会编译错误。

例如,下面是一个计算两个数相加的示例:

public class Adder {
    
    
    public int add(int a, int b) {
    
    
        return a + b;
    }

    public double add(double a, double b) {
    
    
        return a + b;
    }
}

在上面的示例中,Adder 类中定义了两个名为 add 的方法,一个接受两个 int 类型的参数,另一个接受两个 double 类型的参数。通过参数列表的类型不同,重载了 add 方法,实现了对整数和小数的相加操作。

七,方法简单练习

1,数组遍历

需求:设计一个方法用于遍历数组,要求遍历的结果在一行上的。例如:[11, 12, 13, 14, 15]。

可以通过以下方式设计一个方法来遍历数组,并将结果打印在一行上:

public class ArrayTraversal {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    11, 12, 13, 14, 15};
        traverseArray(array);
    }
    
    public static void traverseArray(int[] array) {
    
    
        System.out.print("[");
        for (int i = 0; i < array.length; i++) {
    
    
            System.out.print(array[i]);
            if (i != array.length - 1) {
    
    
                System.out.print(", ");
            }
        }
        System.out.println("]");
    }
}

在上面的示例中,定义了一个名为 traverseArray 的方法,接受一个 int 类型的数组作为参数。在方法内部,使用 for 循环遍历数组元素,并在每个元素之后打印逗号和空格(除非是最后一个元素)。最后,打印右括号,完成整个数组的遍历结果。

运行上述代码,输出结果为:[11, 12, 13, 14, 15]

2,数组最大值

需求:设计一个方法求数组的最大值,并将最大值返回。

你可以使用以下方法来设计一个方法,以获取数组中的最大值并返回:

public class ArrayMaxValue {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    11, 12, 13, 14, 15};
        int maxValue = findMaxValue(array);
        System.out.println("The maximum value in the array is: " + maxValue);
    }
    
    public static int findMaxValue(int[] array) {
    
    
        int maxValue = array[0];
        for (int i = 1; i < array.length; i++) {
    
    
            if (array[i] > maxValue) {
    
    
                maxValue = array[i];
            }
        }
        return maxValue;
    }
}

在上述示例中,我们定义了一个名为 findMaxValue 的方法,它接受一个 int 类型的数组作为参数,并返回数组中的最大值。

在方法内部,我们初始化一个变量 maxValue 并将其设置为数组的第一个元素。然后,我们使用 for 循环遍历数组的剩余元素,并检查每个元素是否大于 maxValue。如果是,则更新 maxValue 的值为当前元素的值。最终,我们返回 maxValue 的值。

运行上述代码,输出结果为:The maximum value in the array is: 15

3,判断是否存在

需求:定义一个方法判断一个数组中的某一个数是否存在,将结果返回给调用处。

你可以使用以下方法来设计一个方法,以判断一个数组中是否存在某个数,并将结果返回给调用处:

public class ArrayContainsNumber {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    11, 12, 13, 14, 15};
        int number = 14;
        boolean containsNumber = checkNumber(array, number);
        System.out.println("The array contains the number " + number + ": " + containsNumber);
    }
    
    public static boolean checkNumber(int[] array, int number) {
    
    
        for (int i = 0; i < array.length; i++) {
    
    
            if (array[i] == number) {
    
    
                return true;
            }
        }
        return false;
    }
}

在上述示例中,我们定义了一个名为 checkNumber 的方法,它接受一个 int 类型的数组和一个要判断的数作为参数,并返回一个 boolean 类型的值。

在方法内部,我们使用 for 循环遍历数组的每个元素,并检查当前元素是否等于要判断的数。如果相等,则返回 true 表示数组中存在该数。如果遍历完数组后仍未找到相等的数,则返回 false 表示数组中不存在该数。

运行上述代码,输出结果为:The array contains the number 14: true

4,复制数组

需求:定义一个方法copyOfRange(int[] arr, int from, int to)
功能:将数组arr中从索引from(包含from)开始。
到索引to结束(不包含to)的元素复制到新数组中,将数组返回。

你可以使用以下方法来实现将一个数组中指定范围的元素复制到一个新数组中:

public class ArrayCopyOfRange {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 2, 3, 4, 5, 6};
        int from = 2;
        int to = 5;
        int[] newArr = copyOfRange(arr, from, to);
        
        System.out.print("Original Array: ");
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i] + " ");
        }
        
        System.out.println();
        
        System.out.print("New Array: ");
        for (int i = 0; i < newArr.length; i++) {
    
    
            System.out.print(newArr[i] + " ");
        }
    }
    
    public static int[] copyOfRange(int[] arr, int from, int to) {
    
    
        int[] newArr = new int[to - from];
        int index = 0;
        
        for (int i = from; i < to; i++) {
    
    
            newArr[index] = arr[i];
            index++;
        }
        
        return newArr;
    }
}

在上述示例中,我们定义了一个名为 copyOfRange 的方法,它接受一个 int 类型的数组、一个起始索引 from 和一个结束索引 to 作为参数,并返回一个新的 int 类型的数组。

在方法内部,我们首先创建一个新数组 newArr,其长度为 to - from,即要复制的元素的数量。然后,使用一个循环从原始数组的索引 from 开始遍历到索引 to - 1,并将每个元素复制到新数组中。

最后,将新数组返回给调用处。在 main 方法中,我们使用一个示例数组和起始索引 2 和结束索引 5 来测试 copyOfRange 方法。运行上述代码,将输出:

Original Array: 1 2 3 4 5 6
New Array: 3 4 5

八,方法的基本内存原理

在Java中,方法在内存中的执行和存储主要涉及两个概念:栈内存和堆内存。

  1. 栈内存(Stack Memory):

    • 方法调用时,会在栈内存中创建一个新的栈帧(Stack Frame),栈帧中存储了方法的局部变量、参数、方法返回值等信息。
    • 栈内存具有后进先出的特性,每次方法调用时,会将栈帧压入栈顶,方法执行完后,栈帧会被弹出。
    • 栈内存的大小是有限的,当方法的调用层次过深或方法中的局部变量占用空间过大时,可能会导致栈溢出错误(Stack Overflow Error)。
  2. 堆内存(Heap Memory):

    • 对象、数组等动态分配的内存空间都存储在堆内存中。
    • 堆内存的大小一般比较大,不容易被耗尽。
    • 堆内存的分配和释放由Java虚拟机(JVM)的垃圾回收机制负责。

方法的执行过程如下:

  1. 当一个方法被调用时,会在栈内存中创建一个新的栈帧,并将该栈帧压入栈顶。
  2. 栈帧中会包含方法的局部变量、参数以及方法返回值的存储空间。
  3. 方法执行时,会在栈帧中分配内存空间来存储局部变量。
  4. 方法执行完后,栈帧会被弹出,释放相应的内存空间。
  5. 方法的返回值会被保存在栈帧中,并传递给调用方法。

需要注意的是,方法的参数传递是按值传递的,即传递的是变量的副本而不是变量本身。对于引用类型的参数,传递的是引用的副本,而不是引用指向的对象本身。因此,在方法中对参数进行修改,不会影响原始变量或对象的值。

九,什么是基本数据类型和引用数据类型

在Java中,数据类型分为基本数据类型(Primitive Data Types)和引用数据类型(Reference Data Types)。

  1. 基本数据类型:
    基本数据类型是Java语言中最基本的数据类型,它们是预定义的,由Java的虚拟机直接支持。基本数据类型包括:

    • 整型(int、short、long、byte)
    • 浮点型(float、double)
    • 字符型(char)
    • 布尔型(boolean)

    基本数据类型的特点:

    • 占用的内存空间固定,不会随着数据的大小而改变。
    • 赋值时直接存储的是数据的值本身,而不是引用。
    • 存储在栈内存中。
  2. 引用数据类型:
    引用数据类型指的是通过类、接口或数组创建的类型。引用数据类型的变量存储的是对象的引用(内存地址),而不是对象本身。

    • 类型(Class)
    • 接口(Interface)
    • 数组(Array)

    引用数据类型的特点:

    • 占用的内存空间大小不固定,由对象的大小决定。
    • 赋值时存储的是对象的引用,通过引用可以访问对象的属性和方法。
    • 存储在堆内存中。
    • 需要通过关键字"new"来创建对象。

需要注意的是,基本数据类型和引用数据类型在传递参数时有所不同。基本数据类型的参数传递是按值传递的,而引用数据类型的参数传递是按引用传递的。即基本数据类型的参数传递是传递值的副本,而引用数据类型的参数传递是传递引用的副本。

十,方法的值传递

在Java中,方法的参数传递采用的是值传递(Pass by Value)。

值传递的意思是在调用方法时,实际参数的值会被复制给形式参数,而方法中对形式参数的修改不会影响到实际参数的值。

具体来说,Java中方法的值传递有以下几点特点:

  1. 基本数据类型的值传递:当将一个基本数据类型作为参数传递给方法时,传递的是该数据的值的副本。在方法内部对形式参数的修改不会影响到实际参数的值。
  2. 引用数据类型的值传递:当将一个对象作为参数传递给方法时,传递的是该对象的引用的副本。在方法内部对形式参数的修改会影响到实际参数指向的对象,但是如果在方法内部将形式参数重新指向一个新的对象,不会影响到实际参数的引用。

下面通过示例代码来说明方法的值传递:

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int a = 10;
        changeValue(a);
        System.out.println(a); // 输出:10
        
        StringBuilder sb = new StringBuilder("Hello");
        changeReference(sb);
        System.out.println(sb.toString()); // 输出:Hello World
        
        changeValueReference(sb);
        System.out.println(sb.toString()); // 输出:Hello Java
    }
    
    public static void changeValue(int num) {
    
    
        num = 20;
    }
    
    public static void changeReference(StringBuilder str) {
    
    
        str.append(" World");
    }
    
    public static void changeValueReference(StringBuilder str) {
    
    
        str = new StringBuilder("Hello Java");
    }
}

在上述示例中,changeValue方法尝试修改基本数据类型的值,但是对传入的实际参数a没有产生影响。
changeReference方法通过引用类型参数对传入的StringBuilder对象进行修改,影响了实际参数sb的值。
changeValueReference方法尝试将形式参数str指向一个新的StringBuilder对象,但是对实际参数sb没有产生影响。

十一,综合练习

1,买飞机票

需求:机票的价格按照淡季旺季、头等舱和经济舱、输入机票原价、月份和头等舱或经济舱。
按照如下规则计算机票价格:旺季(5-10月)头等舱9折。经济舱8.5折,淡季(11月到来年4月)头等舱7折,经济舱6.5折。

下面是一个示例代码,根据输入的机票原价、月份和头等舱或经济舱,按照规则计算机票价格:

import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("请输入机票原价:");
        double originalPrice = scanner.nextDouble();
        
        System.out.print("请输入月份(1-12):");
        int month = scanner.nextInt();
        
        System.out.print("请输入舱位(1-头等舱,2-经济舱):");
        int cabinType = scanner.nextInt();
        
        double discount = getCabinDiscount(month, cabinType);
        double finalPrice = originalPrice * discount;
        
        System.out.println("机票折扣后的价格为:" + finalPrice);
    }
    
    public static double getCabinDiscount(int month, int cabinType) {
    
    
        if (month >= 5 && month <= 10) {
    
     // 旺季
            if (cabinType == 1) {
    
     // 头等舱
                return 0.9;
            } else if (cabinType == 2) {
    
     // 经济舱
                return 0.85;
            }
        } else if (month >= 11 || month <= 4) {
    
     // 淡季
            if (cabinType == 1) {
    
     // 头等舱
                return 0.7;
            } else if (cabinType == 2) {
    
     // 经济舱
                return 0.65;
            }
        }
        
        return 1.0; // 默认折扣为1,即原价
    }
}

在上述代码中,我们使用Scanner类获取用户的输入,包括机票原价、月份和舱位类型。
然后,通过调用getCabinDiscount方法计算机票的折扣,该方法根据输入的月份和舱位类型返回相应的折扣率。
最后,把机票原价乘以折扣率得到机票的最终价格,并输出给用户。

例如,如果用户输入机票原价为1000,月份为8,舱位类型为1(头等舱),则输出的机票折扣后的价格为900。

2,找质数

需求:判断101-200之间有多少个素数,并输出索引素数。

下面是一个示例代码,用于判断101-200之间有多少个素数,并输出素数的索引:

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int count = 0;
        for (int i = 101; i <= 200; i++) {
    
    
            if (isPrime(i)) {
    
    
                count++;
                System.out.println("第 " + count + " 个素数是:" + i);
            }
        }
        System.out.println("101-200之间共有 " + count + " 个素数");
    }
    
    public static boolean isPrime(int n) {
    
    
        if (n <= 1) {
    
    
            return false;
        }
        for (int i = 2; i <= Math.sqrt(n); i++) {
    
    
            if (n % i == 0) {
    
    
                return false;
            }
        }
        return true;
    }
}

在上述代码中,我们使用一个循环遍历101-200之间的数。对于每个数,调用isPrime方法来判断它是否为素数。如果是素数,则输出该素数的索引(即素数的个数)和值。

isPrime方法实现了判断一个数是否为素数的逻辑。它首先判断如果数小于等于1,则不是素数,直接返回false。然后,使用一个循环从2开始到该数的平方根,依次检查是否能被整除。如果找到能整除的数,则不是素数,返回false。如果循环结束后仍然没有找到能整除的数,则是素数,返回true。

执行以上代码,将输出101-200之间共有多少个素数,并输出每个素数的索引和值。

3,开发验证码

需求:定义方法实现随机产生一个5位的验证码。
验证码格式:长度为5,前面四位是大写的字母或者小写字母,最后一位是数字。

下面是一个实现随机生成一个5位验证码的示例代码:

import java.util.Random;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        String code = generateCode();
        System.out.println("生成的验证码是:" + code);
    }
    
    public static String generateCode() {
    
    
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        
        // 生成前4位字母
        for (int i = 0; i < 4; i++) {
    
    
            // 随机生成字母的ASCII码
            int ascii = random.nextInt(26);
            // 判断是大写字母还是小写字母
            char letter = (random.nextBoolean() ? 'A' : 'a');
            // 拼接字母到验证码
            sb.append((char)(letter + ascii));
        }
        
        // 生成最后1位数字
        int number = random.nextInt(10);
        sb.append(number);
        
        return sb.toString();
    }
}

在上述代码中,我们定义了一个generateCode方法来生成验证码。使用一个StringBuilder对象来拼接生成的字符。

首先,我们使用Random类来生成随机数。在一个循环中,我们生成4个随机字母。通过生成随机的ASCII码(0-25),并根据随机布尔值来决定是生成大写字母还是小写字母。然后,我们将生成的字母拼接到验证码中。

最后,我们使用nextInt(10)生成一个0-9的随机数字,并将其拼接到验证码的最后一位。

执行以上代码,将输出随机生成的5位验证码。

4,数组元素的复制

需求:把一个数组的元素复制到另一个新数组中去。

下面是一个实现数组元素复制的示例代码:

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int[] arr1 = {
    
    1, 2, 3, 4, 5};
        int[] arr2 = copyArray(arr1);
        
        System.out.println("原始数组:");
        for (int num : arr1) {
    
    
            System.out.print(num + " ");
        }
        
        System.out.println("\n复制后的数组:");
        for (int num : arr2) {
    
    
            System.out.print(num + " ");
        }
    }
    
    public static int[] copyArray(int[] arr) {
    
    
        int[] newArr = new int[arr.length];
        
        // 遍历原始数组,将每个元素复制到新数组中
        for (int i = 0; i < arr.length; i++) {
    
    
            newArr[i] = arr[i];
        }
        
        return newArr;
    }
}

在上述代码中,我们定义了一个copyArray方法来实现数组元素的复制。我们传入一个原始数组,创建一个新数组newArr,长度与原数组相同。

然后,我们使用一个循环遍历原始数组,将每个元素复制到新数组中的对应位置。

最后,我们返回新数组。

执行以上代码,将输出原始数组和复制后的数组。

5,评委打分

需求:在唱歌比赛中,有6名评委给选手打分,分数范围是【0-100】之间的整数。选手的最后得分为:去掉最高分、最低分后的4个评委的平均分,请完成上述过程并计算出选手的得分。

下面是一个实现评委打分的示例代码:

import java.util.Arrays;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int[] scores = {
    
    90, 95, 88, 92, 96, 85};
        double averageScore = calculateAverageScore(scores);
        
        System.out.println("评委打分:" + Arrays.toString(scores));
        System.out.println("选手得分:" + averageScore);
    }
    
    public static double calculateAverageScore(int[] scores) {
    
    
        // 对打分数组进行排序
        Arrays.sort(scores);
        
        // 去掉最高分和最低分的总分
        int totalScore = 0;
        for (int i = 1; i < scores.length - 1; i++) {
    
    
            totalScore += scores[i];
        }
        
        // 计算平均分
        double averageScore = (double) totalScore / (scores.length - 2);
        return averageScore;
    }
}

在上述代码中,我们定义了一个calculateAverageScore方法来计算选手的得分。我们传入一个评委打分的数组。

首先,我们使用Arrays.sort方法对打分数组进行排序,这样最高分和最低分就会分别位于数组的首尾。

然后,我们使用一个循环遍历排序后的打分数组,从第二个元素开始累加总分,直到倒数第二个元素。

最后,我们计算去掉最高分和最低分的总分的平均值,并将其作为选手的得分返回。

执行以上代码,将输出评委的打分和选手的得分。

6,数字加密和解密

加密

需求:某系统的数字密码(大于0),比如1983,采用加密方式进行传输。
规则:先得到每位数,然后每位数都加上5,在对10求余,最后将所有数字反转,得到一串新数。

下面是一个实现数字加密的示例代码:

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int password = 1983;
        int encryptedPassword = encryptPassword(password);
        
        System.out.println("原始密码:" + password);
        System.out.println("加密后的密码:" + encryptedPassword);
    }
    
    public static int encryptPassword(int password) {
    
    
        // 将密码转换为字符串
        String passwordStr = String.valueOf(password);
        
        // 将每位数加上5并对10求余
        StringBuilder encryptedPasswordStr = new StringBuilder();
        for (int i = 0; i < passwordStr.length(); i++) {
    
    
            int digit = Character.getNumericValue(passwordStr.charAt(i));
            int encryptedDigit = (digit + 5) % 10;
            encryptedPasswordStr.append(encryptedDigit);
        }
        
        // 反转字符串得到加密后的密码
        String reversedPasswordStr = encryptedPasswordStr.reverse().toString();
        int encryptedPassword = Integer.parseInt(reversedPasswordStr);
        
        return encryptedPassword;
    }
}

在上述代码中,我们定义了一个encryptPassword方法来对密码进行加密。我们传入一个大于0的数字密码。

首先,我们将密码转换为字符串,方便处理每位数。

然后,我们使用一个循环遍历密码的每位数,将每位数加上5并对10求余,得到加密后的每位数。我们使用StringBuilder来构建加密后的密码字符串。

接下来,我们将加密后的密码字符串反转,得到加密后的密码字符串。

最后,我们将加密后的密码字符串转换为整数形式,并将其作为加密后的密码返回。

执行以上代码,将输出原始密码和加密后的密码。

解密

下面是一个实现数字解密的示例代码:

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int encryptedPassword = 8321;
        int decryptedPassword = decryptPassword(encryptedPassword);
        
        System.out.println("加密后的密码:" + encryptedPassword);
        System.out.println("解密后的密码:" + decryptedPassword);
    }
    
    public static int decryptPassword(int encryptedPassword) {
    
    
        // 将加密后的密码转换为字符串
        String encryptedPasswordStr = String.valueOf(encryptedPassword);
        
        // 反转字符串得到加密前的密码
        StringBuilder decryptedPasswordStr = new StringBuilder(encryptedPasswordStr).reverse();
        
        // 将每位数减去5并对10求余
        StringBuilder passwordStr = new StringBuilder();
        for (int i = 0; i < decryptedPasswordStr.length(); i++) {
    
    
            int digit = Character.getNumericValue(decryptedPasswordStr.charAt(i));
            int passwordDigit = (digit + 5) % 10;
            passwordStr.append(passwordDigit);
        }
        
        // 将加密前的密码字符串转换为整数形式,并将其作为解密后的密码返回
        int decryptedPassword = Integer.parseInt(passwordStr.toString());
        
        return decryptedPassword;
    }
}

在上述代码中,我们定义了一个decryptPassword方法来对加密后的密码进行解密。我们传入一个加密后的密码。

首先,我们将加密后的密码转换为字符串。

然后,我们将加密后的密码字符串反转,得到加密前的密码字符串。

接下来,我们使用一个循环遍历加密前的密码字符串的每位数,将每位数减去5并对10求余,得到解密后的每位数。我们使用StringBuilder来构建解密后的密码字符串。

最后,我们将解密后的密码字符串转换为整数形式,并将其作为解密后的密码返回。

执行以上代码,将输出加密后的密码和解密后的密码。

7,抢红包

需求:一个主播直播抽奖,奖品是现金红包,分别有{2,588,888,1000, 10000}五个奖金。请使用代码模拟抽奖,打印出每个奖项,奖项的出现顺序要随机且不重复。打印效果如下:(随机顺序,不一定是下面的顺序)
2元的奖金被抽出
588元的奖金被抽出
888元的奖金被抽出
1000元的奖金被抽出
10000元的奖金被抽出

以下是实现抢红包的示例代码:

import java.util.Random;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int[] prizes = {
    
    2, 588, 888, 1000, 10000};
        
        shufflePrizes(prizes);
        
        for (int prize : prizes) {
    
    
            System.out.println(prize + "元的奖金被抽出");
        }
    }
    
    public static void shufflePrizes(int[] prizes) {
    
    
        Random random = new Random();
        
        for (int i = prizes.length - 1; i > 0; i--) {
    
    
            int j = random.nextInt(i + 1);
            
            int temp = prizes[i];
            prizes[i] = prizes[j];
            prizes[j] = temp;
        }
    }
}

在上述代码中,我们使用数组prizes存储奖金金额。然后我们调用shufflePrizes方法来打乱奖金顺序。

shufflePrizes方法中,我们使用Fisher-Yates算法对奖金数组进行随机打乱。通过迭代数组,我们在每次迭代中使用nextInt方法生成一个随机索引j(范围是0到i),然后交换当前迭代索引i和随机索引j处的奖金金额。

最后,我们在main方法中遍历打乱后的奖金数组,并打印每个奖项。

执行以上代码,将输出每个奖项,奖项的出现顺序是随机的且不重复。

8,双色球彩票系统

需求:投注号码由6个红色球号码和1个蓝色球号码组成。红色球号码从1-33中选择;蓝色号码从1-16中选择。

中奖条件和奖金表

奖等 中奖条件 中奖说明 奖金
一等奖 红球6个,篮球1个 中6+1 1000万
二等奖 红球6个,篮球0个 中6+0 500万
三等奖 红球5个,篮球1个 中5+1 3000元
四等奖 红球5个,篮球0个
红球4个,篮球1个
中5+0
中4+1
200元
五等奖 红球4个,篮球1个
红球3个,篮球1个
中4+0
中3+1
10元
六等奖 红球2个,篮球1个
红球1个,篮球1个
红球0个,篮球1个
中2+1
中1+1
中0+1
5元

以下是一个简单的双色球彩票系统的Java代码实现:

import java.util.Arrays;
import java.util.Random;

public class DoubleColorBallLottery {
    
    
    private static final int RED_BALL_COUNT = 6;
    private static final int MAX_RED_BALL_NUMBER = 33;
    private static final int MAX_BLUE_BALL_NUMBER = 16;

    private static final int FIRST_PRIZE = 10000000; // 一等奖奖金
    private static final int SECOND_PRIZE = 5000000; // 二等奖奖金
    private static final int THIRD_PRIZE = 3000; // 三等奖奖金
    private static final int FOURTH_PRIZE = 200; // 四等奖奖金
    private static final int FIFTH_PRIZE = 10; // 五等奖奖金
    private static final int SIXTH_PRIZE = 5; // 六等奖奖金

    private static final int[] FIRST_PRIZE_CONDITION = {
    
    6, 1}; // 一等奖中奖条件
    private static final int[] SECOND_PRIZE_CONDITION = {
    
    6, 0}; // 二等奖中奖条件
    private static final int[] THIRD_PRIZE_CONDITION = {
    
    5, 1}; // 三等奖中奖条件
    private static final int[] FOURTH_PRIZE_CONDITION = {
    
    5, 0, 4, 1}; // 四等奖中奖条件
    private static final int[] FIFTH_PRIZE_CONDITION = {
    
    4, 1, 3, 1}; // 五等奖中奖条件
    private static final int[] SIXTH_PRIZE_CONDITION = {
    
    2, 1, 1, 1, 0, 1}; // 六等奖中奖条件

    public static void main(String[] args) {
    
    
        int[] winningNumbers = generateWinningNumbers();
        int[] userNumbers = generateUserNumbers();
        int blueBall = generateBlueBall();

        System.out.println("中奖号码:" + Arrays.toString(winningNumbers) + " 蓝球:" + blueBall);
        System.out.println("用户号码:" + Arrays.toString(userNumbers) + " 蓝球:" + blueBall);

        int prizeLevel = checkPrizeLevel(winningNumbers, userNumbers, blueBall);
        switch (prizeLevel) {
    
    
            case 1:
                System.out.println("恭喜您中一等奖!奖金:" + FIRST_PRIZE + "元");
                break;
            case 2:
                System.out.println("恭喜您中二等奖!奖金:" + SECOND_PRIZE + "元");
                break;
            case 3:
                System.out.println("恭喜您中三等奖!奖金:" + THIRD_PRIZE + "元");
                break;
            case 4:
                System.out.println("恭喜您中四等奖!奖金:" + FOURTH_PRIZE + "元");
                break;
            case 5:
                System.out.println("恭喜您中五等奖!奖金:" + FIFTH_PRIZE + "元");
                break;
            case 6:
                System.out.println("恭喜您中六等奖!奖金:" + SIXTH_PRIZE + "元");
                break;
            default:
                System.out.println("很遗憾,未中奖");
                break;
        }
    }

    // 生成中奖号码
    private static int[] generateWinningNumbers() {
    
    
        int[] winningNumbers = new int[RED_BALL_COUNT];
        Random random = new Random();
        for (int i = 0; i < RED_BALL_COUNT; i++) {
    
    
            int number = random.nextInt(MAX_RED_BALL_NUMBER) + 1;
            while (containsNumber(winningNumbers, number)) {
    
    
                number = random.nextInt(MAX_RED_BALL_NUMBER) + 1;
            }
            winningNumbers[i] = number;
        }
        Arrays.sort(winningNumbers);
        return winningNumbers;
    }

    // 生成用户号码
    private static int[] generateUserNumbers() {
    
    
        int[] userNumbers = new int[RED_BALL_COUNT];
        Random random = new Random();
        for (int i = 0; i < RED_BALL_COUNT; i++) {
    
    
            int number = random.nextInt(MAX_RED_BALL_NUMBER) + 1;
            while (containsNumber(userNumbers, number)) {
    
    
                number = random.nextInt(MAX_RED_BALL_NUMBER) + 1;
            }
            userNumbers[i] = number;
        }
        Arrays.sort(userNumbers);
        return userNumbers;
    }

    // 生成蓝球号码
    private static int generateBlueBall() {
    
    
        Random random = new Random();
        return random.nextInt(MAX_BLUE_BALL_NUMBER) + 1;
    }

    // 检查中奖等级
    private static int checkPrizeLevel(int[] winningNumbers, int[] userNumbers, int blueBall) {
    
    
        int redBallCount = countRedBalls(winningNumbers, userNumbers);
        boolean hasBlueBall = blueBall == userNumbers[RED_BALL_COUNT - 1];

        if (Arrays.equals(userNumbers, winningNumbers)) {
    
    
            return 1;
        } else if (redBallCount == FIRST_PRIZE_CONDITION[0] && hasBlueBall) {
    
    
            return 2;
        } else if (redBallCount == THIRD_PRIZE_CONDITION[0] && hasBlueBall) {
    
    
            return 3;
        } else if (redBallCount == FOURTH_PRIZE_CONDITION[0] && hasBlueBall) {
    
    
            return 4;
        } else if (redBallCount == FOURTH_PRIZE_CONDITION[2] && hasBlueBall) {
    
    
            return 4;
        } else if (redBallCount == FIFTH_PRIZE_CONDITION[0] && hasBlueBall) {
    
    
            return 5;
        } else if (redBallCount == FIFTH_PRIZE_CONDITION[2] && hasBlueBall) {
    
    
            return 5;
        } else if (redBallCount == SIXTH_PRIZE_CONDITION[0] && hasBlueBall) {
    
    
            return 6;
        } else if (redBallCount == SIXTH_PRIZE_CONDITION[2] && hasBlueBall) {
    
    
            return 6;
        } else if (redBallCount == SIXTH_PRIZE_CONDITION[4] && hasBlueBall) {
    
    
            return 6;
        } else if (!hasBlueBall) {
    
    
            return 0;
        } else {
    
    
            return -1;
        }
    }

    // 统计红球个数
    private static int countRedBalls(int[] winningNumbers, int[] userNumbers) {
    
    
        int count = 0;
        for (int userNumber : userNumbers) {
    
    
            if (containsNumber(winningNumbers, userNumber)) {
    
    
                count++;
            }
        }
        return count;
    }

    // 检查数组中是否包含指定的数字
    private static boolean containsNumber(int[] numbers, int number) {
    
    
        for (int i : numbers) {
    
    
            if (i == number) {
    
    
                return true;
            }
        }
        return false;
    }
}

在上述代码中,我们使用generateWinningNumbers方法和generateUserNumbers方法分别生成中奖号码和用户号码,生成的号码均为6个红球号码和1个蓝球号码。

然后使用generateBlueBall方法生成一个蓝球号码。

接下来,我们使用checkPrizeLevel方法检查用户号码是否中奖,并返回中奖等级。该方法根据奖金表中的中奖条件来判断中奖等级。

最后,根据返回的中奖等级,我们打印中奖信息和奖金金额。

执行以上代码,将输出中奖号码、用户号码以及中奖信息。

9,二维数组

Java中的二维数组是由多个一维数组组成的数据结构,它可以看作是一个表格或者是一个矩阵。二维数组在Java中被定义为一个数组的数组,即数组的元素也是数组。

(1)二维数组静态初始化

在Java中,可以使用静态初始化的方式创建和初始化二维数组。静态初始化是指在声明数组的同时为数组元素赋值。以下是静态初始化二维数组的示例:

dataType[][] arrayName = {
    
    
    {
    
    value1, value2, value3},
    {
    
    value4, value5, value6},
    {
    
    value7, value8, value9}
};

在上面的示例中,dataType表示二维数组中元素的数据类型,arrayName是数组的名称,{value1, value2, value3}表示第一行的元素,{value4, value5, value6}表示第二行的元素,{value7, value8, value9}表示第三行的元素。

可以根据需要添加或删除行和列,使二维数组具有不同的大小。每一行中的元素个数可以不同,从而创建不规则的二维数组。

以下是一个静态初始化二维数组的完整示例:

int[][] matrix = {
    
    
    {
    
    1, 2, 3},
    {
    
    4, 5, 6},
    {
    
    7, 8, 9}
};

// 访问二维数组的元素
int element = matrix[1][2]; // 访问第二行第三列的元素,即6

// 遍历二维数组的所有元素
for (int i = 0; i < matrix.length; i++) {
    
    
    for (int j = 0; j < matrix[i].length; j++) {
    
    
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

上述示例中,创建了一个3x3的二维数组,然后通过索引访问其中的元素,并使用嵌套循环遍历二维数组中的所有元素。输出结果为:

1 2 3 
4 5 6 
7 8 9

(2)二维数组动态初始化

在Java中,可以使用动态初始化的方式创建和初始化二维数组。动态初始化是指在声明数组的同时指定数组的大小,然后使用循环或其他方式为数组元素赋值。以下是动态初始化二维数组的示例:

dataType[][] arrayName = new dataType[rowSize][columnSize];

在上面的示例中,dataType表示二维数组中元素的数据类型,arrayName是数组的名称,rowSize表示数组的行数,columnSize表示数组的列数。

以下是一个动态初始化二维数组的完整示例:

int rowSize = 3;
int columnSize = 3;
int[][] matrix = new int[rowSize][columnSize];

// 为二维数组赋值
for (int i = 0; i < rowSize; i++) {
    
    
    for (int j = 0; j < columnSize; j++) {
    
    
        matrix[i][j] = i + j;
    }
}

// 访问二维数组的元素
int element = matrix[1][2]; // 访问第二行第三列的元素,即3

// 遍历二维数组的所有元素
for (int i = 0; i < rowSize; i++) {
    
    
    for (int j = 0; j < columnSize; j++) {
    
    
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

上述示例中,首先通过new关键字动态创建了一个3x3的二维数组,然后使用嵌套循环为数组元素赋值。接着,通过索引访问其中的元素,并使用嵌套循环遍历二维数组中的所有元素。输出结果为:

0 1 2 
1 2 3 
2 3 4

(3)二维数组内存图

下面是一个Java二维数组的内存图示例:

+---------+
|   row0  | -> +-------+
|         |    |   1   |
+---------+    +-------+
|   row1  | -> +-------+
|         |    |   2   |
+---------+    +-------+
|   row2  | -> +-------+
|         |    |   3   |
+---------+    +-------+

在内存中,二维数组被存储为一组连续的内存块。每个内存块表示数组的一行,内存块的大小取决于数组元素的类型。在上面的示例中,二维数组的行数为3,列数为1,因此内存中有3个连续的内存块。

每个内存块中存储了数组元素的值。在上面的示例中,第一行的元素值为1,第二行的元素值为2,第三行的元素值为3。

要访问二维数组中的特定元素,可以使用索引。例如,要访问第二行第一个元素的值,可以使用arrayName[1][0]。在上面的示例中,arrayName[1][0]的值为2。

需要注意的是,Java中的二维数组是一维数组的数组。也就是说,二维数组实际上是一个包含了其他一维数组的数组。每个一维数组代表二维数组的一行。在内存中,二维数组的每个元素实际上是一个指向一维数组的引用。

(4)计算每个季度的销售额

下面是一个使用二维数组计算每个季度的销售额的Java案例:

public class Sales {
    
    
    public static void main(String[] args) {
    
    
        // 定义二维数组sales,表示每个季度的销售额
        double[][] sales = {
    
    
            {
    
    1500.0, 2000.0, 1800.0},   // 第一季度的销售额
            {
    
    2200.0, 2500.0, 2300.0},   // 第二季度的销售额
            {
    
    1800.0, 2100.0, 1900.0},   // 第三季度的销售额
            {
    
    2500.0, 2800.0, 2600.0}    // 第四季度的销售额
        };

        // 计算每个季度的总销售额
        double[] totalSales = new double[4];
        for (int i = 0; i < sales.length; i++) {
    
    
            double total = 0.0;
            for (int j = 0; j < sales[i].length; j++) {
    
    
                total += sales[i][j];
            }
            totalSales[i] = total;
        }

        // 输出每个季度的总销售额
        for (int i = 0; i < totalSales.length; i++) {
    
    
            System.out.println("第" + (i+1) + "季度的总销售额为:" + totalSales[i]);
        }
    }
}

在上面的案例中,我们使用一个二维数组sales表示每个季度的销售额。数组的每一行代表一个季度,每一列代表一个月份。我们首先定义了这个二维数组,并将每个季度的销售额初始化。

接下来,我们创建一个一维数组totalSales,用于存储每个季度的总销售额。然后,通过嵌套的循环遍历二维数组,计算每个季度的总销售额,并将结果存储到totalSales数组中。

最后,我们遍历totalSales数组,输出每个季度的总销售额。

运行以上代码,将会输出每个季度的总销售额。

猜你喜欢

转载自blog.csdn.net/m0_62617719/article/details/132558890