java - 理解一段Java代码

标签 java logic

在使用一些代码库时,我试图理解一段代码,以便可以工作和自定义它,我能够理解几乎 90% 的代码流程。这是整体流程

  1. 代码用于生成 15 位代码(字母数字),前 3 位数字由客户提供。
  2. 最初代码生成 16 位字母数字并将其存储在缓存中。
  3. 客户可以通过指定数量生成任意数量的代码。
  4. 所有客户生成的代码都是根据 16 位数字生成的(第 2 点)。生成的所有代码都包含该 16 位字母数字中的数字/字母。
  5. 当有人尝试使用这些代码时,系统会尝试验证所提供的代码是否有效。

我对用于确定所提供的代码是否有效的逻辑感到震惊,这是那段代码,我生成 6 个代码作为示例,在这种情况下,生成并存储在缓存中的字母数字代码是

 initial-alphabet : M9W6K3TENDGSFAL4

基于initial-alphabet生成的代码是 myList=[123-MK93-ES6D-36F3、123-MK93-EFTW-D3LG、123-MK93-EALK-TGLD、123-MK93-ELKK-DN6S、123-MK93-E4D9-3A6T、123-MK93- EMTW-LNME]

 protected  int getVoucherNumber(String voucherCode){
  int voucherNumberPos = voucherCode.length() - 12;
  String voucherNumberHex = voucherCode.substring(voucherNumberPos, voucherNumberPos + 6);
  int firstByte = getIntFromHexByte(voucherNumberHex.substring(0, 2), 0);
  int secondByte = getIntFromHexByte(voucherNumberHex.substring(2, 4), 1);
  int thirdByte = getIntFromHexByte(voucherNumberHex.substring(4, 6), 7);
  return firstByte << 16 | secondByte << 8 | thirdByte;
}

private int getIntFromHexByte(String value, int offset){
  return (getIntFromHexNibble(value.charAt(0), offset) << 4) + getIntFromHexNibble(value.charAt(1), offset + 4);
} 

private int getIntFromHexNibble(char value, int offset){
  int pos = getAlphabet().indexOf(value);
  if (pos == -1) {// nothing found}
    pos -= offset;
  while (pos < 0) {
    pos += 16;
  }
    return pos % 16;
 }

这是尝试验证代码的代码

 int voucherNumber = getVoucherNumber(kyList.get(4));

在本例中,voucherNumber 的值为 4,即列表中的第四个元素,以防我传递不属于列表的任何值 getVoucherNumber 方法返回更高的值(大于列表计数)。

让我困惑的主要事情之一是这两行

int voucherNumberPos = voucherCode.length() - 12;
String voucherNumberHex = voucherCode.substring(voucherNumberPos, voucherNumberPos + 6);

根据我的理解,他们首先从客户提供的支票中移出前 3 位数字,但他们同样没有使用字符串的其余部分,而只使用了字符串的特定部分。

谁能帮我理解这一点

最佳答案

看来您继承了一些编写糟糕的代码的责任。我们都经历过这样的情况,所以我会尝试本着这种精神来回答。我不确定这个问题是否是该网站的主题,但帮助中心似乎并未禁止。为了尽量切入主题,我将提供一些一般性建议,但不限于问题的高度本地化细节。

myList.get(4)

Java 中的数组是从零开始的,因此是 123-MK93-E4D9-3A6T。您可能知道这一点,但从您的问题中并不清楚您是否知道。

initial-alphabet : M9W6K3TENDGSFAL4

我认为这是在 getIntFromHexNibble 中调用 getAlphabet 返回的结果。因此,代码中的字母数字字符应该是十六进制,但使用一组非标准的 16 个字符作为数字。

protected  int getVoucherNumber(String voucherCode){

忽略连字符和客户提供的前三位数字,代码为“MK93E4D93A6T”。 12 个十六进制数字编码 48 位,但 Java 中的 int 只有 32 位长,因此代码已经被破坏。无论它做什么,都不会返回优惠券代码代表的优惠券编号。

int voucherNumberPos = voucherCode.length() - 12;
String voucherNumberHex = voucherCode.substring(voucherNumberPos, voucherNumberPos + 6);

这会将oucherNumberHex 设置为一个六字符长字符串,从voucherCode 末尾开始十二个字符,在本例中是93-E4D。当第一次编写此代码时,作者似乎并没有期望调用者包含连字符。即便如此,其意图似乎是忽略一半的优惠券代码。

int firstByte = getIntFromHexByte(voucherNumberHex.substring(0, 2), 0);
int secondByte = getIntFromHexByte(voucherNumberHex.substring(2, 4), 1);
int thirdByte = getIntFromHexByte(voucherNumberHex.substring(4, 6), 7);

乍一看这看起来很简单,但参数 017 根本不是偏移量,尽管参数的名称是这样的争论。它试图将每对十六进制数字转换为一个字节,如果没有连字符,这将是足够合理的。现在是有趣的部分:

private int getIntFromHexNibble(char value, int offset) {
    int pos = getAlphabet().indexOf(value);
    if (pos == -1) {// nothing found}
        pos -= offset;

        while (pos < 0) {
            pos += 16;
        }
        return pos % 16;
    }

“found”后面的右大括号被注释掉了,所以你发布的代码实际上是不完整的。我假设还有另外一两行内容为

    return pos;
}

因此,基本思想是通过调用 indexOfM 变为 0,9 变为 1,依此类推。但是,如果此方法发现一个字符不在提供的字母表中,例如连字符,它会使用所谓的 offset 来计算默认值(在本例中为 14,如果我在我的头是对的),并将其作为十六进制半字节值返回。

最终结果是您返回 0(含)到 2^24(不含)范围内的数字。但是,在此类数字应具有的 2^24 个可能值中,只会返回 2^20 个不同的值。因此,对于看起来像 12 位 32 位数字的优惠券代码(其值将是一个天文数字),每个客户前缀中的不同优惠券编号仅限于略高于一百万个。

一般建议:

  • 使用同行评审来防止此类代码进入 生产。
  • 使用单元测试来证明代码执行该功能 名字说确实如此。
  • 如果输入不是,则使用异常提前失败 你所期待的。

关于java - 理解一段Java代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26268530/

相关文章:

java - CDI - bean 实例的可重用性

java - 如何对图的节点进行排序,使两个相邻节点之间的距离最小

css - 根据内容显示/隐藏同级 div

c - 如何使用格式说明符修复 C 程序中的输出?程序正在运行,但输出不符合预期

java - JsonInclude.Include.NON_DEFAULT 不适用于自定义序列化程序

java - 从 MySQL 获取最后一个 id

java - 使用嵌套 for 循环初始化 2D 数组并查找模式

java - 如何实现可测试、可维护的实时逻辑?

xna - 沿对角线移动 Sprite

java - 使用 Java 和 Selenium,如何选择下拉列表中的所有选项?