slug
type
status
category
date
summary
tags
password
icon

第二次月考23题:

 
Let’s carefully trace the execution step by step.

Given behavior of Checker.validate(Item i)

  • lastID starts at 0
  • If i.getIdNum() == lastID → print invalid
  • Otherwise → update lastID to the new id and print valid

Objects created

So:
  • i has ID 23
  • j has ID 55
  • c.lastID = 0
Assume checkID(c) simply calls:

Execution trace

1️⃣ i.checkID(c);

  • id = 23
  • lastID = 0
  • 23 != 0valid
  • Update lastID = 23
Output:

2️⃣ j.checkID(c);

  • id = 55
  • lastID = 23
  • 55 != 23valid
  • Update lastID = 55
Output:

3️⃣ j.checkID(c);

  • id = 55
  • lastID = 55
  • 55 == 55invalid
  • lastID unchanged
Output:

4️⃣ i.checkID(c);

  • id = 23
  • lastID = 55
  • 23 != 55valid
  • Update lastID = 23
Output:

✅ Final printed output (in order)



 

Activity 4.9.9.

 
 
我直接按从上到下、几乎每一行给你讲一遍在干嘛,也顺便帮你串一下整体逻辑。

  • import 语句:告诉 Java 编译器“我要用 java.util 这个包里的类”。
  • java.util 里有很多集合类,比如 ArrayList, HashMap 等。
  • 表示导入这个包中所有公共类
    • 在这段代码里,我们实际用到的是:ArrayList

  • 定义一个公共类 WordPairTest
  • 按照 Java 规范:一个 .java 文件里如果有 public 类,那么文件名必须和这个类名完全一致,所以这个文件应该叫 WordPairTest.java
  • 大括号 { 表示这个类的开始。

  • public:主方法对外是公开的,JVM 可以调用它。
  • static:是类方法,不需要创建 WordPairTest 对象就可以直接用类名调用。JVM 启动程序时就是直接调用这个静态方法。
  • void:表示这个方法没有返回值。
  • main:Java 程序的入口方法,固定写法。
  • String[] args:命令行参数(字符串数组),这段代码里没用到。
  • {:主方法体的开始。

  • 这一行是注释// 开头),给人看的,不会被编译器执行。
  • 中文意思:创建一个存放 WordPair 对象的 ArrayList,名字叫 pairs

  • ArrayList<WordPair>:这是一个泛型集合,表示“一个 ArrayList,里面存的是 WordPair 类型的对象”。
    • ArrayList<String> 类似,只不过这里存的是你自定义的 WordPair
  • pairs:变量名,这个变量引用一个 ArrayList 对象。
  • =:赋值运算符,把右边 new 出来的对象赋给左边的变量。
  • new ArrayList<WordPair>()
    • new:在堆内存中创建一个新的 ArrayList 对象。
    • <WordPair> 再写一遍,是旧一点的写法。也可以写成:
    • 整句含义:创建一个空的、用来装 WordPair 对象的动态数组,并用变量 pairs 引用它

    这一行做了两件事:
    1. new WordPair("hi", "there")
        • 调用了下面定义的 WordPair 构造方法,传入两个字符串 "hi""there"
        • 会创建一个 WordPair 对象,其中:
          • word1 = "hi"
          • word2 = "there"
    1. pairs.add( … )
        • addArrayList 的方法,用来把一个元素放到列表的末尾
        • 这里就是:把刚刚创建好的 WordPair("hi", "there") 放进 pairs 这个列表里。

    • 同理,再创建一个 WordPair 对象:
      • word1 = "hi"
      • word2 = "bye"
    • 再把这个对象添加到 pairs 的后面。
    • 此时 pairs 里有两个元素(两个 WordPair 对象):
        1. (hi, there)
        1. (hi, bye)

    • System.out.println(...):向控制台打印内容。
    • 当你打印一个 ArrayList 时,ArrayList 会调用:
      • 每个元素的 toString() 方法来生成字符串,
      • 然后用逗号+空格分隔,外面再加一对方括号 []
    • 我们的 WordPair 类里重写了 toString(),返回 "(" + word1 + ", " + word2 + ")"
    • 所以打印结果会是:

    • 这两个右大括号依次关闭:
      • 最里层 }:结束 main 方法。
      • 外层 }:结束 WordPairTest 类定义。

    从这里开始是第二个类的定义:
    • 定义一个类 WordPair,注意这里 没有写 public,所以它是包可见(同一个包里可以访问,别的包看不到)。
    • 这个类用来表示“一对单词”。

    • 定义两个实例变量(成员变量):
      • word1:存第一 个单词。
      • word2:存第二个单词。
    • private封装性,这两个变量外部类不能直接访问,只能通过方法(getter)访问。
    • String:表示用字符串类型存单词。

    这是 WordPair构造方法
    • 方法名和类名相同 WordPair,说明这是构造器。
    • public:外部可以用 new WordPair(...) 来创建对象。
    • 参数列表:(String word1, String word2)
      • 调用构造方法时需要提供两个字符串。
    • 方法体内部:
      • this.word1 = word1;
        • 左边 this.word1:当前对象的成员变量 word1
        • 右边 word1:方法参数。
        • 等式含义:把传进来的参数赋值给当前对象的成员变量
      • this.word2 = word2; 同理。
    • 为何要用 this
      • 因为参数名和成员变量名相同,用 this.word1 区分“对象里的那个”。

    • 这是一个 getter 方法
    • public:外部可以调用。
    • 返回类型是 String
    • 方法名 getFirst():语义上表示“获得第一个单词”。
    • 方法体只有一句:return word1;
      • 返回当前对象的 word1

    • 同样是 getter。
    • 返回当前对象的 word2

    • public String toString()
      • 这是从 Object 类继承来的方法,这里进行了重写(override)
      • 当你打印对象(System.out.println(obj))或者把对象拼接到字符串时,会自动调用 toString()
    • 方法体:
      • 用字符串拼接,把两个单词包装成一个形如 (hi, there) 的字符串。
      • 如果 word1 = "hi", word2 = "there",那么 toString() 返回:"(hi, there)"
    • 最后的 }:结束 WordPair 类。

    总结一下整体运行流程

    1. 程序从 main 方法开始执行。
    1. 创建一个 ArrayList<WordPair>pairs
    1. pairs 里添加两个 WordPair 对象:
        • "hi", "there"
        • "hi", "bye"
    1. System.out.println(pairs)
        • ArrayList 调用每个 WordPairtoString(),得到:(hi, there)(hi, bye)
        • 然后组合成:[(hi, there), (hi, bye)] 打印出来。

     
     
     

     

    Project 4.9.10.

     
    先给你一个整体图,然后重点讲你关心的「打印部分」是怎么一步一步工作的。

    一、整体在干什么?

    这段代码一共两个类:
    • WordPairsList:负责生成并保存一堆单词对,以及统计相同单词对的个数。
    • WordPair:代表一对单词,比如 (Hi, there)
    main 方法里:
    做了三件事:
    1. 定义一个 String[] 数组 words
    1. 用这个数组创建一个 WordPairsList 对象 list
    1. System.out.println(list); 打印这个对象。

    二、构造方法:生成所有有序单词对 (i < j)

    • allPairs 是一个 ArrayList<WordPair>:里面存的每一个元素都是一个 WordPair 对象。
    • 外层循环:i 从 0 到 words.length - 1
    • 内层循环:ji + 1words.length - 1
    • 条件 j = i+1 保证 永远 i < j,所以不会出现 (words[1], words[0]) 这种“逆序”,也不会出现 (words[0], words[0]) 这种自己跟自己配对。
    对于 {"Hi", "there", "Tyler", "Sam"},索引和单词是:
    • 0 → "Hi"
    • 1 → "there"
    • 2 → "Tyler"
    • 3 → "Sam"
    两层循环生成的配对顺序是:
    1. i = 0
        • j = 1(words[0], words[1]) = (Hi, there)
        • j = 2(Hi, Tyler)
        • j = 3(Hi, Sam)
    1. i = 1
        • j = 2(there, Tyler)
        • j = 3(there, Sam)
    1. i = 2
        • j = 3(Tyler, Sam)
    一共 6 个 WordPair 对象,依次被加进 allPairs 里。

    三、WordPair 类做了什么?

    一个 WordPair 就是“两件事”:
    • 保存两个字符串:word1 / word2
    • 知道自己如何打印:toString() 返回 "(" + word1 + ", " + word2 + ")" 的格式
    比如:
    会调用 p.toString(),输出:

    四、最关键:System.out.println(list); 到底发生了什么?

    来拆开:
    这行代码的逻辑是:
    1. println 要把 list 变成字符串 → 会自动调用 list.toString()
    1. 所以这行代码等价于:
      WordPairsListtoString()
      也就是说:
      • list.toString() 其实就是调用 allPairs.toString()
      再往下一层:allPairs 是一个 ArrayList<WordPair>
      ArrayList 自己有一个内置的 toString() 实现,大致是这样的效果:
      核心点:
      ArrayList 在转成字符串时,会调用每个元素自己的 toString() 方法。
      而我们的元素类型是 WordPair,所以会依次调用每个 WordPairtoString()
      于是整个调用链是:
      1. System.out.println(list);
      1. → 调用 list.toString()
      1. → 返回 allPairs.toString()
      1. ArrayListtoString() 把每个 WordPair 转成字符串
      1. → 每个 WordPair 用自己的 toString() 格式化成 (word1, word2)
      1. 最终结果变成一个大字符串:
      所以你在控制台看到的大约就是这一行(顺序如上)。

      五、numMatches() 方法在干什么?

      虽然你重点问打印,我顺带把这个也讲清楚,你以后写第二部分题目会用到。
      含义:
      • 遍历 allPairs 里的每一个 WordPair
        • wp.getFirst()word1
        • wp.getSecond()word2
      • 如果两个字符串 .equals(),说明这对是 (x, x),也就是两个单词一样,就把 count 加 1。
      • 最后返回这样的配对个数。
      在当前的 words = {"Hi", "there", "Tyler", "Sam"} 情况下:
      • 生成的 6 个 pair 里,没有任何一个是 (同一个单词, 同一个单词)
      • 所以 numMatches() 会返回 0
      如果你改一改 words,比如:
      生成的 pair 是:
      • (Hi, Hi)
      • (Hi, Sam)
      • (Hi, Sam)
      此时:
      • (Hi, Hi) 计数一次
      • (Hi, Sam) 不计
      • (Hi, Sam) 不计
      那么 numMatches() 返回就是 1

      六、你可以自己验证一下打印结果

      如果在 main 里把 numMatches() 的测试也打开:
      输出大概是:

      七、总结一下打印逻辑的“调用链”

      用一条线帮你记忆:
      如果你愿意,我也可以帮你把这一整段改成“手动打印”的版本,比如用 for 循环一个个打印 WordPair,这样你会对 toString()println 的关系更有感觉。
       
       

      第二次月考23题

      Building a websiteCSAWESOME 4.6代码详解
      Loading...