4

我是 Java 语言的新手,我尝试编写我的第一个相对复杂的程序。在我写了几个类之​​后,我意识到我几乎没有直接使用内置类(如 BigInteger、MessageDigest、ByteBuffer),因为它们并不完全符合我的需求。相反,我编写自己的类,并在类内部使用内置类作为属性。例子:

public class SHA1 {
    public static final int SHA_DIGEST_LENGTH = 20;

    private MessageDigest md;

    public SHA1() {
        try {
            md = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public void update(byte[] data) {
        md.update(data);
    }

    public void update(BigNumber bn) {
        md.update(bn.asByteArray());
    }

    public void update(String data) {
        md.update(data.getBytes());
    }

    public byte[] digest() {
        return md.digest();
    }
}

通过以下简单的类,我在使用 SHA1 时不必使用 try catch,我可以将自定义 BigNumber 类作为参数,也可以将 String 作为参数来更新函数。

以下 BigNumber 类包含我需要的所有函数以及我需要它们的确切方式。

public class BigNumber {
    private BigInteger m_bn;

    public BigNumber() {
        m_bn = new BigInteger("0");
    }

    public BigNumber(BigInteger bn) {
        m_bn = bn;
    }

    public BigNumber(String hex) {
        setHexStr(hex);
    }

    //reversed no minsize
    public byte[] asByteArray() {
        return asByteArray(0, true);
    }

    //reversed with minsize
    public byte[] asByteArray(int minSize) {
        return asByteArray(minSize, true);
    }

    public byte[] asByteArray(int minSize, boolean rev) {
        byte[] mag = m_bn.toByteArray();

        //delete sign bit
        //there is always a sign bit! so if bitNum % 8 is zero then
        //the sign bit created a new byte (0th)
        if(getNumBits() % 8 == 0) {
            byte[] tmp = new byte[mag.length-1];
            System.arraycopy(mag, 1, tmp, 0, mag.length-1);
            mag = tmp;
        }

        //extend the byte array if needed
        int byteSize = (minSize >= getNumBytes()) ? minSize : getNumBytes();
        byte[] tmp = new byte[byteSize]; 

        //if tmp's length smaller then byteSize then we keep 0x00-s from left
        System.arraycopy(mag, 0, tmp, byteSize-mag.length, mag.length);

        if(rev) ByteManip.reverse(tmp);

        return tmp;
    }

    public String asHexStr() {
        return ByteManip.byteArrayToHexStr(asByteArray(0, false));
    }

    public void setHexStr(String hex) {
        m_bn = new BigInteger(hex, 16);
    }

    public void setBinary(byte[] data) {
        //reverse = true
        ByteManip.reverse(data);
        //set as hex (binary set has some bug with the sign bit...)
        m_bn = new BigInteger(ByteManip.byteArrayToHexStr(data), 16);
    }

    public void setRand(int byteSize) {
        byte[] tmp = new byte[byteSize];
        new Random().nextBytes(tmp);
        //reversing byte order, but it doesn't really matter since it is a random
        //number
        setBinary(tmp);
    }

    public int getNumBytes() {
        return (m_bn.bitLength() % 8 == 0) ? (m_bn.bitLength() / 8) : (m_bn.bitLength() / 8 + 1);
    }

    public int getNumBits() {
        return m_bn.bitLength();
    }

    public boolean isZero() {
        return m_bn.equals(BigInteger.ZERO);
    }

    //operations
    public BigNumber modExp(BigNumber exp, BigNumber mod) {
        return new BigNumber(m_bn.modPow(exp.m_bn, mod.m_bn));
    }

    public BigNumber mod(BigNumber m) {
        return new BigNumber(m_bn.mod(m.m_bn));
    }

    public BigNumber add(BigNumber bn) {
        return new BigNumber(m_bn.add(bn.m_bn));
    }

    public BigNumber subtract(BigNumber bn) {
        return new BigNumber(m_bn.subtract(bn.m_bn));
    }

    public BigNumber multiply(BigNumber bn) {
        return new BigNumber(m_bn.multiply(bn.m_bn));
    }   
}

我的问题是在 Java 语言中使用这些类而不是内置类有多普遍?它是否使其他程序员无法阅读我的代码(与使用内置类实现所有内容相比)?

我读过新的 C++ 程序员拼命地尝试编写他们以前用 C 编写的代码,因此 C++ 的好处对他们来说仍然是隐藏的。恐怕我在 Java 中做了类似的事情:尝试自己实现所有东西,而不是直接使用内置类。这是否发生(例如在 BigNumber 类中)?

感谢您的意见!

4

5 回答 5

3

我通常会编写一个实用程序类来支持我处理逻辑。如

public class CommonUtil{

  public byte[] asByteArray(int minSize)
  {
    return "something".getBytes();
  }

  // add more utility methods

}
于 2012-10-31T18:34:28.583 回答
2

当您通过这样做增加一些价值时,包装一个类是有意义的。如果您要添加小功能,则值得使用实用程序类而不是包装现有的类。

于 2012-10-31T18:37:23.763 回答
1

我认为,如果您没有充分的理由再次实现相同的功能,您可能不应该这样做。这里有几个原因:

  • 内置类被世界各地的很多人使用,因此错误比你的代码少
  • 有 Java 经验的用户在使用标准类方面会比你的类更好,他们将需要更少的时间来理解你的代码并在你的项目中编写新的东西
  • 内置类具有良好的文档,因此使用起来要容易得多
  • 实现由 Java 专业人员实现和测试的东西是在浪费时间。最好专注于自己的项目
  • 如果您正在编写一个长期项目,您将需要支持您的所有课程。Oracle 已经支持内置类。让他们做他们的工作!
  • 最后的但并非最不重要的。你确定你比内置类的作者更了解这个问题吗?只有答案是肯定的,才考虑编写自己的实现。即使是日常使用的类(例如集合或与时间相关的类)的实现也可能很棘手。
于 2012-10-31T18:46:30.240 回答
1

通过创建一个为您做这些事情的课程,您不会获得任何东西。如果您要经常执行某些操作,那么您可能想要创建一个带有静态方法的新类,为您完成这些重要的事情。

假设您始终需要一个排序数组。您可以创建一个新课程,我们称之为SortedArray. 您可以在添加某些内容时对其进行排序,但是当您可以添加所有内容然后调用(实用程序)方法Arrays.sort时,为什么要这样做呢?对于常见操作,请查看 Java 的Arrays类 - 如果您经常做某事,那是您为其创建方法的东西,例如搜索和排序。在您的情况下,您可以创建一个实用方法,将 BigInteger 转换为您的字节数组。您不应该只是制作自己的“更好”版本来满足您的需求。当其他人查看您的代码时,使用标准对象会好得多,而不是使用不使用的自定义对象.

于 2012-10-31T18:48:12.810 回答
0

正如@Shark 评论的那样,创建自己的解决方案没有意义,因为:

  1. 他们需要时间来创造
  2. 他们变得不那么灵活

但是,您可以扩展类(推荐)或使用可能更适合您的 3rd 方框架。

于 2012-10-31T18:37:21.527 回答