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

クラスをラップすることは、そうすることによって何らかの価値を追加するときに意味があります。小さな機能を追加する場合は、既存のクラスをラップする代わりに、Utilityクラスを使用する価値があります。

于 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. 彼らはそれほど柔軟になりません

ただし、クラスを拡張することも(推奨)、より適切なサードパーティのフレームワークを使用することもできます。

于 2012-10-31T18:37:21.527 に答える