Java, насколько распространено расширение / упаковка встроенных классов
Я новичок в языке 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();
}
}
В следующем простом классе мне не нужно использовать try catch при использовании SHA1, я могу поместить свой собственный класс 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)?
Спасибо за ваши мнения!
5 ответов
Обертывание класса имеет смысл, когда вы добавляете некоторую ценность таким образом. Если вы добавляете небольшую функциональность, может быть стоит использовать класс Utility вместо того, чтобы переносить существующий класс.
Я обычно пишу служебный класс, который будет помогать мне обрабатывать логику. Такие как
public class CommonUtil{
public byte[] asByteArray(int minSize)
{
return "something".getBytes();
}
// add more utility methods
}
Вы ничего не получите, создав класс, который сделает это за вас. Если вы собираетесь много выполнять определенные операции, то, возможно, вы захотите создать новый класс со статическими методами, которые выполняют эти важные для вас вещи.
Давайте предположим, что вы хотите отсортированный массив в любое время. Вы могли бы сделать новый класс, давайте назовем его SortedArray
, Вы можете сортировать это всякий раз, когда добавляете что-то, но зачем вам это делать, если вы можете просто добавить все и затем вызвать (утилиту) метод Arrays.sort? Для общих операций взгляните на класс Arrays в Java - если вы делаете что-то часто, это то, для чего вы создаете метод, например, поиск и сортировку. В вашем случае вы можете создать служебный метод, который превратит BigInteger в байтовый массив для вас. Вы не должны просто делать свою собственную, "лучшую" версию, которая делает то, что вы хотите. Когда другие люди смотрят на ваш код, когда вы используете стандартные объекты, это намного лучше, чем использование пользовательских объектов, которые на самом деле ничего не делают.
Я думаю, что если у вас нет веских оснований для повторной реализации той же функциональности, вам, вероятно, не стоит этого делать. Вот несколько причин:
- Встроенные классы используются многими людьми по всему миру, и поэтому ошибок меньше, чем в вашем коде
- Пользователи, имеющие опыт работы с Java, будут лучше использовать стандартные классы, чем ваши классы, и им потребуется меньше времени, чтобы понять ваш код и написать что-то новое в вашем проекте.
- Встроенные классы имеют хорошую документацию, поэтому их гораздо проще использовать
- Вы тратите свое время на реализацию чего-то, что было реализовано и протестировано профессионалами Java. Лучше сосредоточиться на собственном проекте
- Если вы пишете долгосрочный проект, вам нужно будет поддерживать все ваши классы. Oracle уже поддерживает встроенные классы. Пусть они делают свою работу!
- Последнее, но не менее важное. Вы уверены, что знаете больше о проблеме, чем автор встроенного класса? Только если ответ положительный, подумайте над написанием собственной реализации. Даже реализация ежедневно используемых классов, таких как коллекции или связанные со временем классы, может быть сложной.
Как прокомментировал @Shark, создавать собственные решения бессмысленно, потому что:
- Они занимают время, чтобы создать
- Они становятся не такими гибкими
Тем не менее, вы можете расширить классы (рекомендуется) или использовать сторонние фреймворки, которые могут вам лучше подойти.