簡體   English   中英

Java擴展/包裝內置類的常見方式

[英]Java how common is extending/wrapping built-in classes

我是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類中)?

謝謝你的意見!

我通常會編寫一個實用程序類來支持我處理邏輯。

public class CommonUtil{

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

  // add more utility methods

}

通過這樣做來添加一些值時,包裝類是有意義的。 如果要添加小功能,則可以使用Utility類而不是包裝現有類。

我認為如果你沒有很好的理由再次實現相同的功能,你不應該這樣做。 原因如下:

  • 內置類被世界各地的許多人使用,因此錯誤比代碼中的錯誤少
  • 具有Java經驗的用戶在使用標准類方面比在類中更好,他們需要更少的時間來理解代碼並在項目中編寫新內容
  • 內置類具有良好的文檔,因此使用它們要容易得多
  • 您正在通過實施由Java專業人員實施和測試的內容來浪費您的時間。 最好專注於自己的項目
  • 如果您正在編寫一個長期項目,則需要支持所有課程。 Oracle已經支持內置類。 讓他們做好自己的工作!
  • 最后的但並非最不重要的。 你確定你比內置類的作者更了解這個問題嗎? 只有答案是肯定的,考慮編寫自己的實現。 即使是日常使用的類的實現,例如集合或與時間相關的類也可能是棘手的。

你沒有通過為你做這個東西的課程來獲得任何東西。 如果您要進行大量的某些操作,那么您可能希望使用靜態方法創建一個新類,為您執行這些重要操作。

我們假設您始終需要排序數組。 你可以創建一個新類,我們稱之為SortedArray 你可以在添加內容時對其進行排序,但是當你可以添加所有內容然后調用(實用程序)方法Arrays.sort時,為什么要這樣做呢? 對於常見的操作,請看一下Java的Arrays類 - 如果你經常做一些事情,那就是你為方法做的事情,比如搜索和排序。 在您的情況下,您可以創建一個實用程序方法,將BigInteger轉換為字節數組。 你不應該只是制作自己的,“更好”的版本來做你想要的。 當其他人查看你的代碼時,當你使用標准對象時,它會好得多,而不是讓自定義對象沒有真正做任何事情

正如@Shark評論的那樣,創建自己的解決方案毫無意義,因為:

  1. 他們需要時間來創造
  2. 它們變得不那么靈活了

但是,您可以擴展類(建議使用它)或使用可能更適合您的第三方框架。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM