Переопределение “равняется” методу: как выяснить тип параметра?

MATLAB's ДЛЯ цикл статичен по своей природе; Вы не можете изменить переменную цикла между повторениями, в отличие от этого, для (инициализация; условие; инкремент) циклическая структура на других языках. Это означает, что следующий код всегда печатает 1, 2, 3, 4, 5 независимо от значения B.

A = 1:5;

for i = A
    A = B;
    disp(i);
end

, Если Вы хотите быть в состоянии ответить на изменения в структуре данных во время повторений, , В ТО ВРЕМЯ КАК цикл может быть более соответствующим---, Вы будете в состоянии протестировать условие цикла при каждом повторении и установить значение переменной (переменных) цикла, как Вы желаете:

n = 10;
f = n;
while n > 1
    n = n-1;
    f = f*n;
end
disp(['n! = ' num2str(f)])

Btw, для - каждый цикл в Java (и возможно другие языки) производит неуказанное поведение, когда структура данных изменяется во время повторения. Если необходимо изменить структуру данных, необходимо использовать соответствующее Итератор экземпляр, который позволяет дополнение и удаление элементов в наборе, которого Вы выполняете итерации. Хорошие новости - то, что MATLAB поддерживает объекты Java, таким образом, можно сделать что-то вроде этого:

A = java.util.ArrayList();
A.add(1);
A.add(2);
A.add(3);
A.add(4);
A.add(5);

itr = A.listIterator();

while itr.hasNext()

    k = itr.next();
    disp(k);

    % modify data structure while iterating
    itr.remove();
    itr.add(k);

end

19
задан nbro 26 October 2015 в 19:18
поделиться

8 ответов

Это можно сделать, сохранив ссылку на тип Class . Однако, на мой взгляд, проверки равенства должны касаться значений, которые представляют объекты, а не конкретных типов, которые выражаются значениями .

Классическим примером этого является, например, API коллекций. new ArrayList () .equals (new LinkedList ()) возвращает true . Хотя они имеют совершенно разные типы, они представляют одно и то же значение, а именно «пустую коллекцию».

Лично должны быть два Tuple , которые представляют одни и те же данные (например, («a», "b") ) не равно, потому что один имеет тип Tuple , а другой - Tuple ?

15
ответ дан 30 November 2019 в 04:03
поделиться

Because of erasure you can't. About the best you could do is store in the tuple class the type you plan for the Tuple to hold in a "java.lang.Class" field member. Then you could compare those fields to make sure the tuple class is holding the same types.

Also see this thread: Что эквивалентно C ++ Pair в Java?

Будет полезно, если вы разместите больше информации о своем классе. Я думаю, что непроверенное приведение и количество полей, которые вы приравниваете, означают, что это должно быть Tuple нет?

РЕДАКТИРОВАТЬ: вот полезный класс Pair, который я регулярно использую (вы можете адаптировать свой класс Tuple при необходимости) . Обратите внимание: аналогично предложениям других, этот класс просто позволяет содержащимся в нем членам решать вопрос о равенстве. Ваш вариант использования - это то, что должно определить, действительно ли равенство основано на типе содержащихся в нем членов.

/**
 * Adapted from http://forums.sun.com/thread.jspa?threadID=5132045
 * 
 * 
 * @author Tim Harsch
 *
 * @param <L>
 * @param <R>
 */
public class Pair<L, R> {

    private final L left;
    private final R right;

    public R getRight() {
        return right;
    } // end getter

    public L getLeft() {
        return left;
    } // end getter

    public Pair(final L left, final R right) {
        this.left = left;
        this.right = right;
    } // end constructor

    public static <A, B> Pair<A, B> create(A left, B right) {
        return new Pair<A, B>(left, right);
    } // end factory method

    @Override
    public final boolean equals(Object o) {
        if (!(o instanceof Pair<?,?>))
            return false;

        final Pair<?, ?> other = (Pair<?, ?>) o;
        return equal(getLeft(), other.getLeft()) && equal(getRight(), other.getRight());
    } // end method

    public static final boolean equal(Object o1, Object o2) {
        if (o1 == null) {
            return o2 == null;
        }
        return o1.equals(o2);
    } // end method

    @Override
    public int hashCode() {
        int hLeft = getLeft() == null ? 0 : getLeft().hashCode();
        int hRight = getRight() == null ? 0 : getRight().hashCode();

        return hLeft + (37 * hRight);
    } // end method

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('<');
        if( left == null ) {
            sb.append("null");
        } else {
            sb.append(left.toString());
        } // end if
        sb.append(',');
        if( right == null ) {
            sb.append("null");
        } else {
            sb.append(right.toString());
        } // end if
        sb.append('>');
        return sb.toString();
    } // end method
} // end class
4
ответ дан 30 November 2019 в 04:03
поделиться

Поскольку универсальные шаблоны стираются во время компиляции , вы можете в основном т. Во время выполнения любой параметр типа отсутствует, и что касается JVM, они во всех отношениях точно такие же.

Чтобы обойти это, можно сохранить поле Class , представляющее тип, и создать объект с этим типом в конструкторе.

Пример конструктора:

public class Tuple < E > {

    public Tuple(Class<E> c) {
        //store the class
    }

}

Или вы могли бы используйте фабрику:

public static <E> Tuple <E> getTuple(Class<E> type) {
    // Create and return the tuple, 
    // just store that type variable in it 
    // for future use in equals.
}
3
ответ дан 30 November 2019 в 04:03
поделиться

The suggestions to retain a reference to E's type with a Class object seem inefficient (that's a lot of pointless references to a Class taking up memory) and pointless for your problem.

It's not generally true that Foo andFoo should be unequal. So you don't need E. And, in the code you wrote, you don't even need it to compile. Simply cast to Tuple, since that is truly all you know about Tuple at that point. It still compiles and all.

If you are passed Tuples with data of two wildly different types, those elements will not be equals, and your method will return false, as desired. (One hopes -- depends on those types implementing equals sanely.)

2
ответ дан 30 November 2019 в 04:03
поделиться

К сожалению, вы не можете сделать это во время компиляции; информация пропала. Таковы последствия стирания типа . В качестве альтернативы можно сохранить параметр как экземпляр Class , а затем просмотреть его позже.

3
ответ дан 30 November 2019 в 04:03
поделиться

Off-topic - do you realise that according to your implementation, Tuple(a0, a1) is equal to Tuple(a1, a1)? I suspect that's not what you want...

On-topic, as others have said, erasure makes this impossible. But you should reconsider why you want this - equality checking only happens at runtime, and generics are only compile-time. Conceptually, a variable has generic parameters, but an object does not. Thus when you're comparing the equality of objects, the generic parameters do not matter at all; you can't take any appropriate action based on them at runtime anyway.

Object equality, and generic parameter co-/contra-variance, are two orthogonal concerns.

0
ответ дан 30 November 2019 в 04:03
поделиться

Я согласен с комментариями выше, почему класс E должен быть равен? и как вы хотите обрабатывать подклассы E?

В любом случае, учитывая, что вот пример кода, который может вам помочь:

public class Example<T> {

  T t;

  public Example(T t) {
    this.t = t;
  }

  public static void main(String[] args) {
    final String s = "string";
    final Integer i = 1;
    final Number n = 1;

    final Example<String> exampleString = new Example<String>(s);
    final Example<Integer> exampleInteger = new Example<Integer>(i);
    final Example<Number> exampleNumber = new Example<Number>(n);

    System.out.println("exampleString subclass "  + exampleString.t.getClass());
    System.out.println("exmapleIntger subclass " + exampleInteger.t.getClass());
    System.out.println("exmapleNumber subclass " + exampleNumber.t.getClass());
    System.out.println("Integer equals Number = " + 
        exampleInteger.t.equals(exampleNumber.t));
  }
}

Вы можете вызвать t.getClass (), чтобы получить информацию о классе о типе T (при условии, что конечно, это не нуль.)

Надеюсь, это поможет.

0
ответ дан 30 November 2019 в 04:03
поделиться

Используйте отражение. http://tutorials.jenkov.com/java-reflection/generics.html

0
ответ дан 30 November 2019 в 04:03
поделиться
Другие вопросы по тегам:

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