111 - Lecture4

Arrays ,Static Method 1, and Testing

数组、静态方法和测试驱动开发

1. 数组(Arrays)

• 定义:数组是长度固定(fixed-length)的有序数据集合(a ordered collection of data),用于存储同一类型的元素。数组中的每个元素都有一个索引,通过索引可以访问特定元素。

数组可以包含任何给定的数据类型,包括基本数据类型Primitives(如整数、浮点数、字符等)和对象Objects(如自定义的类实例)

java 复制代码
int n = 3;
double[] a;//declare the array
a = new double[n];//creat the array
for (int i = 0;i < n; I++){
	a[I] = 0.0;//initialize all elements to 0.0
}
java 复制代码
int [] a = new int []//创建(construct)一个长度为100的整型数组。

default initialization:

当创建一个数字数组时,所有的元素会自动初始化为0。同样地,当创建一个布尔型数组时,所有的元素会自动初始化为false。这种自动初始化的行为称为默认初始化。

alternative array initialization

• 初始化:可以通过以下两种方式来创建数组:

  1. 静态初始化 :int[] numbers = {1, 2, 3};

  2. 动态初始化:int[] numbers = new int[5];

区别在于初始化数组时是否为数组的元素指定初始值。

Array Operations

  • indexing - 索引访问:a[2]

  • assignment - 赋值:a[2] = 5

  • length - 获取数据长度:a.length

    注意这不是一个方法调用(a method call),所以不需要使用括号(parentheses)。(this is different syntax from String.length())

    • 访问与操作:通过索引来访问或修改数组中的元素,索引从0开始。例如,numbers[0]访问第一个元素。

Printing and Enhanced For Loops

数组是一种引用数据类型(reference data type),这意味着数组变量本身并不直接存储数据,而是存储了数据存储位置的地址信息。在内存中 ,数组变量保存的是数组第一个元素的地址,通过这个地址可以访问到整个数组的数据

• 增强型for循环:可以用简化的for循环来遍历数组中的所有元素(to itrate over all elements in the array),无需索引。

java 复制代码
String[] months = {
	"","Jan","Feb","Mar","Apr","May"
};
System.out.println(months);//printing the address
  • 如果不加双引号,编译器会认为这些是变量名或其他非字符串的值,这会导致编译错误。所以加上双引号可以明确表示这些是字符串。
  • 当你直接打印数组对象 时,输出的并不是数组的内容,而是数组的引用****地址的表示形式
  • 如果想要打印数组内容,应该使用 Arrays.toString() 或遍历数组
java 复制代码
System.out.println(Arrays.toString(months));
java 复制代码
for (元素类型 变量名 : 集合或数组) {
    // 对变量进行操作
}

• 变量名:用于存储当前遍历到的元素。

• 集合或数组:你想要遍历的数组或 Iterable 集合

java 复制代码
for (int i = 1;i < months.length;i++){
	System.out.println(months[i]);
}
java 复制代码
for (String s :months){
	System.out.println(s);
}

String Methods: Trim,Split,Replace

  • String trim()

this string with leading and trailing whitespace(前后空格)removed

  • String replace(String a, String b)

this string with a replaced by b

  • String replaceAll(String a, String b)

this string with all a's replaced by b's

  • String[] split(String delimiter)

array of Strings between occurrences of delimiter(分割符)

java 复制代码
String cosmo = " ha haa halloween ";
cosmo = cosmo.trim();//去掉前后空格
cosmo = cosmo.replaceAll("h","H");
String[] words = bosom.split(" ");//根据空格分割字符串
for (int i = 0;i < words.length;i++){
	System.out.println(words[i]);
}

所以最终结果是一个字符串数组 ["Ha", "Haa", "Halloween"]

java 复制代码
Ha
Haa
Halloween
•	replace() 用于简单的字符串替换。用于替换单个字符或整个字符串
•	replaceAll() 方法用于替换字符串中所有匹配正则表达式的子字符串。与 replace() 不同的是,replaceAll() 支持正则表达式的使用。
java 复制代码
String text = "hello world";
String result = text.replace("l", "L");
System.out.println(result); // 输出 "heLLo worLd"

String text = "hello world";
String result = text.replaceAll("l+", "L");
System.out.println(result); // 输出 "heLo worLd" (将连续的 "l" 替换成 "L")
量词:+ 表示一个或多个字符,* 表示零个或多个字符,? 表示零个或一个字符。
•	示例:[0-9]+ 表示匹配一个或多个数字。

Array Example

• 程序用 0.0 来初始化变量 max。如果数组中所有的元素都小于 0.0(例如负数),最大值将会被错误地保持为 0.0,而不是数组中的实际最大值。

java 复制代码
double[] arr = {2.5, 100.01, 99.99};

double max = arr[0];  // 将 max 初始化为数组的第一个元素

for (int i = 1; i < arr.length; i++) {
    if (arr[i] > max) {
        max = arr[i];
    }
}
System.out.println(max);

Two-dimensional Arrays/Multidimensional Arrays

• 多维数组:Java支持二维或多维数组,可以通过嵌套的方式来创建和访问这些数组。例如:

1. To represent a matrix , or a table of numbers organized in m rows and

n columns, we use a two-dimensional array in Java. use the notation a[i][j]

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

matrix[0][0] = 1;

java 复制代码
 int m = 3, n = 5;
 double[][] a = new double[m][n];

 for (int i = 0; i < m; i++) {
 	for (int j = 0; j < n; j++)
    a[i][j] = i + j + 1.0;
        }
 for (int i = 0; i < m; i++) {            // 外层循环控制行
 	for (int j = 0; j < n; j++) {        // 内层循环控制列
 		System.out.print(a[i][j] + " ");// 输出一行中的每个元素,并在每个元素后加一个空格
                }
    System.out.println();                 // 每输出完一整行后换行
            }
java 复制代码
1.0 2.0 3.0 4.0 5.0
2.0 3.0 4.0 5.0 6.0
3.0 4.0 5.0 6.0 7.0
2. declare and initialize a three-dimensional array
java 复制代码
int n = 5;
double[][][] a = new double[n][n][n];

2. 静态方法(Static Methods)

• 静态方法的定义:使用static关键字定义的方法,属于类本身而不是某个具体的对象。静态方法可以直接通过类名调用,而不需要创建对象。例如:

java 复制代码
public static int add(int a, int b) {
    return a + b;
}

A static method/function call调用时:通过方法名后跟上相应的参数(argument)来执行一个方法或函数。这些参数用逗号分隔,并且整个调用被括号包围(enclosed)。

java 复制代码
int sum = MyClass.add(5, 10);

arguments must match the parameter type(s)

  • 函数和静态方法的基本概念

    • 函数的定义:函数接受输入( take an input)并产生输出(produce an output)。在Java中,函数通常实现为静态方法。

    • 静态方法的使用:比如,Math.abs() 是一个静态方法,它接受一个数值作为参数(argument)并返回它的绝对值。调用这个方法时,我们只需要传递参数,方法返回处理后的结果。

  • 重构为静态方法
    避免代码重复(repeated codes),并且将代码组织成独立的部分,以便于共享和重用这些代码片段来构建更大型的程序
java 复制代码
public class Lecture4Demo{
	public static int larger(int x, int y){
		if (x > y){
			return x;
		}else{//else 可以省略
		return y;
		}
	}
	public static void main(String[] args) {
		System.out.println(larger(2, 5));
		System.out.println(larger(10, 8));
	}
}

return语句用于从方法中返回值 。它会将方法的执行结果返回 给调用者,并终止方法的执行

省略else

• if 块中的 return 确保了当 x > y 时,方法立刻返回结果并终止,剩下的代码不会再执行。

• 当 if 条件不成立时,自然会执行剩下的代码,也就是 return y;,所以不需要 else。

3. 测试驱动开发(Testing & TDD)

测试驱动开发(Test-Driven Development, TDD):

TDD 是一种迭代(iterative)开发过程,测试是在实际代码实现之前编写的。其核心概念包括:

• 提升代码质量:通过提前编写测试来指导开发,确保开发出来的代码能通过测试,从而提高代码的健壮性。

• 简化代码结构:通过TDD,开发者必须把问题拆解为可测试的单元(testable units),这有助于使代码模块化(modular)、结构更加清晰。

Red-Green-Refactor cycle循环:

TDD 通常使用 Red-Green-Refactor 的开发周期:

1.	Red(红色):编写一个失败的测试,代表功能代码尚未编写或功能不完整。
2.	Green(绿色):编写最简单的代码来通过测试,确保测试通过,代码能够运行。
3.	Refactor(重构):测试通过后,对代码进行重构,以提高代码质量,同时确保测试继续通过。

TDD 的过程强调了先编写测试,再根据测试编写实现代码,这种方式确保代码从一开始就具备高可测试性,便于后续维护与扩展。

Testing in main

在Main方法中测试

在开发过程中,我们可以在 main() 方法中手动测试代码的功能,但这样做有以下几个问题:

•	如何追踪测试是否通过/失败?
•	如何组织代码以避免重复?

手动测试虽然能起到基础的功能测试作用,但使用JUnit等测试框架能够更好地组织测试用例,避免手动追踪测试结果。

Testing with JUnit

JUnit测试框架

•	下载与集成JUnit:通过下载两个jar文件(如junit-4.13.2.jar和hamcrest-core-1.3.jar),并将其保存到项目的Library文件夹中。
•	添加测试类:点击主类名称,通过IDE快捷键 Alt + Enter,选择 Create Test 来生成测试类。在这个过程中,可以选择需要为哪些方法生成测试代码。

通过JUnit,开发者可以自动化测试,便于回归测试和追踪代码的质量。

assertEquals

使用JUnit中的 assertEquals 方法来进行单元测试。下面是详细的解释:

• assertEquals 方法用于比较两个值是否相等,它接收两个参数:期望值 (expected) 和 实际输出值 (actual)。

• 如果期望值与实际值相等,测试通过;否则,测试失败。

java 复制代码
import org.junit.Test;
import static org.junit.Assert.*;

public class Lecture4DemoTest {
    
    // 测试当第二个数较大时,larger 方法是否返回正确值
    @Test
    public void testSecondLarger() {
        int output = Lecture4Demo.larger(2, 5);
        assertEquals(5, output); // 期望值为 5,实际输出应为 5
    }

    // 测试当第一个数较大时,larger 方法是否返回正确值
    @Test
    public void testFirstLarger() {
        int output = Lecture4Demo.larger(10, 8);
        assertEquals(10, output); // 期望值为 10,实际输出应为 10
    }
}

assertEquals(expected, actual)

JUnit 使用实例方法(非 static),因为它为每个测试方法创建一个独立的类实例,从而保证测试的隔离性和独立性。因此,测试方法不需要声明为 static。

相关推荐
雷神乐乐11 分钟前
File.separator与File.separatorChar的区别
java·路径分隔符
小刘|16 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
逊嘘35 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
morris13142 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员1 小时前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU1 小时前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie61 小时前
在IDEA中使用Git
java·git
Elaine2023911 小时前
06 网络编程基础
java·网络
G丶AEOM1 小时前
分布式——BASE理论
java·分布式·八股