Как решить проблему: int нельзя разыменовать

Здесь у меня есть некоторое значение, два из которых являются целыми, и я не могу вызвать для них метод, поскольку они не являются ссылкой. Как я могу это решить?

String srcAddr, dstAddr, protocol;
int srcPort, dstPort;

public int hashCode() {

        final int prime = 31;
        int result = 1;
        result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
        result = prime * result + ((dstPort == null) ? 0 : dstPort.hashCode());
        result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
        result = prime * result + ((srcPort == null) ? 0 : srcPort.hashCode());
        return result;

}

Кроме того, у меня есть метод equal, часть его с ошибкой показана ниже, что, как и выше, я не могу сравнить int с нулем.

@Override
public boolean equals(Object obj) {

    if (srcPort == null) {
        if (other.srcPort != null)
            return false;
    } else if (!srcPort.equals(other.srcPort))
        return false;

    if (srcPort == null) {
        if (other.srcPort != null)
            return false;
    } else if (!srcPort.equals(other.srcPort))
        return false;
}

Как я могу решить эту ошибку?


person Red Lion    schedule 14.08.2010    source источник


Ответы (7)


Для метода hashcode вы можете просто оставить целые числа как есть. Ints — это их собственные хэш-коды. Для метода equals просто сравните их, используя =. Итак, код становится:

public class Connection {

    String srcAddr, dstAddr, protocol; int srcPort, dstPort;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
        result = prime * result + dstPort;
        result = prime * result
                + ((protocol == null) ? 0 : protocol.hashCode());
        result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
        result = prime * result + srcPort;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Connection other = (Connection) obj;
        if (dstAddr == null) {
            if (other.dstAddr != null)
                return false;
        } else if (!dstAddr.equals(other.dstAddr))
            return false;
        if (dstPort != other.dstPort)
            return false;
        if (protocol == null) {
            if (other.protocol != null)
                return false;
        } else if (!protocol.equals(other.protocol))
            return false;
        if (srcAddr == null) {
            if (other.srcAddr != null)
                return false;
        } else if (!srcAddr.equals(other.srcAddr))
            return false;
        if (srcPort != other.srcPort)
            return false;
        return true;
    }

}

Написание правильных реализаций hashCode и equals сложно. Лучше используйте свою IDE для их создания. Я вот тоже так сделал.

person Abhinav Sarkar    schedule 14.08.2010

Написание hashcode и equals может быть утомительным и/или подверженным ошибкам, и IDE, такие как Eclipse, могут фактически автоматизировать эту задачу за вас. Существует множество сторонних библиотек, которые также могут облегчить эту функциональность.

Чтобы использовать что-то из стандартной библиотеки, рекомендую сделать следующее:

import java.util.Arrays;

// conveniently packs varargs to array 
private static Object[] pack(Object... objs) {
   return objs;
}

private Object[] fieldsAsArray() {
   return pack(srcAddr, dstAddr, protocol, srcPort, dstPort);
}

@Override public int hashCode() {
   return Arrays.hashCode(this.fieldsAsArray());
}

@Override public boolean equals(Object o) {
   // TODO: instanceof check, cast and assign o to other

   return Arrays.equals(this.fieldsAsArray(), other.fieldsAsArray());
}

Здесь используются varargs, автоупаковка и java.util.Arrays реализация служебного метода для равенства и хэш-кода массивов. Это будет иметь адекватную (хотя, возможно, и не оптимальную) производительность, но код будет кратким и читаемым, и его всегда можно будет оптимизировать позже, если/когда это будет необходимо.


Варианты сторонних библиотек

Из Apache Commons Lang вы можете использовать EqualsBuilder и HashCodeBuilder.

В документации есть пример типичного использования:

@Override public boolean equals(Object obj) {
   if (obj == null) { return false; }
   if (obj == this) { return true; }
   if (obj.getClass() != this.getClass()) {
     return false;
   }
   MyClass other = (MyClass) obj;
   return new EqualsBuilder()
                 .appendSuper(super.equals(obj))
                 .append(field1, other.field1)
                 .append(field2, other.field2)
                 .append(field3, other.field3)
                 .isEquals();
}

@Override public int hashCode() {
   return new HashCodeBuilder(17, 37)
                 .append(field1)
                 .append(field2)
                 .append(field3)
                 .toHashCode();
} 

Полученный код очень удобочитаем, прост в сопровождении и менее подвержен ошибкам.

Похожие вопросы

person polygenelubricants    schedule 14.08.2010

Вам нужно использовать упакованные примитивы, в частности Integer . Для каждого примитива есть аналогичный объект, и они определяют интересующие вас методы (hashCode,equals).

person Nate W.    schedule 14.08.2010

Инициализируйте целые числа чем-то (скажем, -1) и сравните их с -1

Я не понимаю, почему вы хотите получить хэш-код целого числа. Hashcode принимает объект и возвращает уникальное (?) целое число на основе объекта. Целое число — это просто примитивный объект, и вам нужно получить от него хэш-код, чтобы идентифицировать его.

Я бы просто ссылался на целые числа напрямую и имел бы проверку на -1 (если вы инициализируете их до -1) вместо проверки на ноль. (Насколько я понимаю, порт никогда не бывает -1, поправьте меня, если это не так)

person Raynos    schedule 14.08.2010
comment
hashCode() не возвращает уникальное целое число для каждого объекта. (Это невозможно - если вы можете закодировать состояние любого объекта в 32-битном целом, вы нарушаете законы теории информации). - person Jesper; 14.08.2010

srcPort и dstPort являются примитивными int.

В вашем методе hashCode() вы сравниваете dstPort и srcPort с null. Вы не можете сделать это с примитивными типами в Java. Просто напишите строки в методе hashCode() следующим образом:

result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + dstPort;
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + srcPort;

В вашем методе equals() вы пытаетесь вызвать метод equals() для srcPort. Вы не можете вызывать методы примитивных типов в Java. Используйте == для сравнения примитивных типов.

Обратите внимание, что ваш метод equals() также дважды содержит один и тот же блок кода; это скорее всего ошибка. И разве вам не нужно также проверять srcAddr и dstAddr в вашем методе equals()? Что такое other в вашем методе equals()? Это полный код или только его часть?

person Jesper    schedule 14.08.2010
comment
спасибо за Ваш ответ. да, это было частью mycode, а другое - Flows other = (Flows) obj; Я понял суть и понял, в чем была моя проблема. - person Red Lion; 14.08.2010

Я думаю, что у Shakedown есть ответ для вас, просто использовал упакованный тип Integer следующим образом:

String srcAddr, dstAddr, protocol; Integer srcPort, dstPort;

public int hashCode() {

    final int prime = 31;
    int result = 1;
    result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
    result = prime * result + ((dstPort == null) ? 0 : dstPort);
    result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
    result = prime * result + ((srcPort == null) ? 0 : srcPort);
    return result;

}

или, альтернативно, используйте 0 в качестве значения по умолчанию (поскольку это то, что вы возвращаете, если значение все равно не установлено), например:

String srcAddr="", dstAddr=""; int srcPort=0,dstPort=0; //empty string has hashCode 0

public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + dstAddr.hashCode();
  result = prime * result + dstPort;
  result = prime * result + srcAddr.hashCode();
  result = prime * result + srcPort;
  return result;
}

Таким образом, вам не нужно беспокоиться о неявных затратах на автоматическое упаковывание, если это проблема.

person Asaf    schedule 14.08.2010
comment
Effective Java 2nd Edition, Item 49: Предпочитайте примитивы примитивам в штучной упаковке. Бокс в Integer иногда удобен/необходим, но я бы не рекомендовал его для полей. - person polygenelubricants; 14.08.2010

Здесь есть две проблемы. Во-первых, int, объявленные на уровне класса как переменные экземпляра или класса, всегда инициализируются значением. Неважно, какое это значение, они определены как нечто, даже если вы не делаете это явно. Во-вторых, нет смысла вызывать hashCode() для чего-то примитивного типа, поскольку у них нет методов, которые вы можете вызывать.

Моя реализация будет выглядеть примерно так:

public int hashCode() {

        final int prime = 31;
        int result = 1;
        result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
        result = prime * result + dstPort;
        result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
        result = prime * result + srcPort.hashCode;
        return result;

}

public boolean equals(Object obj) {
    if (!(obj instanceof MyClass)) {
        return false;
    }

    //Cast obj to a MyClass

    if (other.srcPort != scrPort) {
            return false;
    }

    if (other.dstPort != dstPort) {
            return false;
    }

    //Check the other variables too.

    //We didn't fall into any if-statements.
    return true;
}
person Thomas Owens    schedule 14.08.2010
comment
Неправда. Неинициализированный int в методе остается неинициализированным, как и любая другая переменная. - person user207421; 15.08.2010
comment
Это верное утверждение. Однако его int объявлены вне метода. Я пересмотрю свой пост, чтобы сделать это явно ясным. - person Thomas Owens; 15.08.2010