理解Java代码片段

Ume*_*thi 0 java logic

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

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

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

 initial-alphabet : M9W6K3TENDGSFAL4
Run Code Online (Sandbox Code Playgroud)

基于initial-alphabetmyList = 生成的代码[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;
 }
Run Code Online (Sandbox Code Playgroud)

这是试图验证代码的代码

 int voucherNumber = getVoucherNumber(kyList.get(4));
Run Code Online (Sandbox Code Playgroud)

在这种情况下,值voucherNumber4来自列表的第四个元素,如果我传递任何不属于list getVoucherNumber方法的值,则返回更高的值(大于列表计数).

困扰我的主要原因之一是这两行

int voucherNumberPos = voucherCode.length() - 12;
String voucherNumberHex = voucherCode.substring(voucherNumberPos, voucherNumberPos + 6);
Run Code Online (Sandbox Code Playgroud)

根据我的理解,他们首先从支票中移出前三位数,这是客户提供的,但他们又没有使用其余的字符串,只是字符串的特定部分.

任何人都可以帮助我理解这一点

gat*_*kin 5

看来你已经继承了一些写得不好的代码的责任.我们都去过那里,所以我会试着以这种精神回答.我不是肯定这个问题是关于这个网站的主题,但它似乎并没有被帮助中心禁止.为了保持主题,我将以一些不仅限于问题的高度本地化细节的一般建议结束.

myList.get(4)
Run Code Online (Sandbox Code Playgroud)

Java中的数组是从零开始的,所以就是这样123-MK93-E4D9-3A6T.你可能知道这一点,但你的问题并不清楚.

initial-alphabet : M9W6K3TENDGSFAL4
Run Code Online (Sandbox Code Playgroud)

我想这是什么通过调用返回到getAlphabetgetIntFromHexNibble.因此,代码中的字母数字字符应为十六进制,但对数字使用非标准的16个字符集.

protected  int getVoucherNumber(String voucherCode){
Run Code Online (Sandbox Code Playgroud)

忽略连字符和客户提供的前三位数字,代码为"MK93E4D93A6T".十二进制数字编码48位,但intJava中只有32位长,因此代码已经被破坏.无论它做什么,它都不会返回凭证代码所代表的凭证号码.

int voucherNumberPos = voucherCode.length() - 12;
String voucherNumberHex = voucherCode.substring(voucherNumberPos, voucherNumberPos + 6);
Run Code Online (Sandbox Code Playgroud)

这是将voucherNumberHex设置为六个字符长的字符串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);
Run Code Online (Sandbox Code Playgroud)

这看起来很简单,但参数0,1并且7根本不是偏移,尽管参数的名称.它试图将每对十六进制数字转换为一个字节,如果不是连字符,这将是足够明智的.现在是有趣的部分:

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;
    }
Run Code Online (Sandbox Code Playgroud)

"found"之后的右大括号已被注释掉,因此您发布的代码实际上是不完整的.我将假设还有另外一两行阅读

    return pos;
}
Run Code Online (Sandbox Code Playgroud)

所以基本的想法是通过调用M变为0,9变为1,依此类推indexOf.但是如果这个方法看到的字符不在提供的字母表中,比如连字符,它会使用所谓offset的计算默认值(在这种情况下为14,如果我已经在我头脑中完成了数学计算),并返回作为十六进制半字节值.

最终结果是您返回0(含)到2 ^ 24(不包括)范围内的数字.但是在这个数字应该具有的2 ^ 24个可能值中,将仅返回2 ^ 20个不同的值.因此,从看起来像基数为32的十二位数的凭证代码(其具有天文数字的值),您在每个客户前缀内限制为略多于一百万个不同的凭证数.

一般建议:

  • 使用同行评审来防止此类代码投入生产.
  • 使用单元测试来证明代码执行函数名称所说的功能.
  • 如果输入不是您所期望的,则使用异常提前失败.