2016-01-11 3 views
2
Vector v = new Vector(); 
String a = "element"; 
String b = "element"; 
v.add(a); 
v.contains(b) // true 

Так что мой вопрос: если тип элементов в vector являются Object, чем как contains сравнить Object внутри с String снаружи, если equals() не перекрываться как Object я хотел бы знать, что происходит под поверхностью.Java: Объекты в коллекции

+0

«под поверхностью» 'a == b' на самом деле истинно, потому что они являются одинаковыми строковыми литералами –

ответ

3

См here:

Возвращает true, если этот вектор содержит заданный элемент. Более формально возвращает true тогда и только тогда, когда этот вектор содержит хотя бы один элемент e такой, что (o==null ? e==null : o.equals(e)).

.equals, который в конечном итоге называется переопределенным .equals. Тот факт, что параметр метода вводится с номером Object, не означает, что вектор будет использовать метод .equals класса Object; он будет использовать переопределенный метод .equals, если он существует (в противном случае используется один, унаследованный от Object). Набираемый параметр Object означает, что вы можете передать все, что есть Object (что String есть, так как все классы Java наследуют от Object).

Вашей путаница проистекает из того факта, что метод вызывается при выполнении зависят от фактического типа объекта, метод которого в настоящее время вызывается. Посмотрите раздел JLS на runtime evalution of method invocations для более подробной информации. Вы можете видеть, что в нем упоминается «целевая ссылка», которая является объектом, метод которого вы вызываете.

Рассмотрим, что произойдет иначе: поведение будет меняться в зависимости от типа параметра метода, а не типа экземпляра. Это полностью победит полиморфизм! Рассмотрим часто используемый пример Animal: допустим, существует один метод, называемый makeNoise(), который возвращает строку "Noise!". Теперь у вас есть два подкласса Dog и Cat, которые переопределили метод для возврата "Woof!" и "Meow!" соответственно. Давайте теперь у вас есть этот метод:

public void animalNoiseMaker(Animal animal) { 
    System.out.println(animal.makeNoise()); 
} 

Идущий на ваши ожидания, независимо от того, прошли ли вы в случае Dog или Cat, было бы назвать makeNoise на Animal каждый раз, и печать Noise!, так как тип параметра Animal. Это не очень полезное поведение.

+0

и почему не нужно вводить объект внутри как' String'? Как компилятор знает, как обрабатывать ссылку внутри вектора? –

+1

JVM знает во время выполнения, какой тип цели. –

1

Vectorcontains метод «S вызывает indexOf, который сравнивает элементы Vector с элементом, мы ищем с помощью equals.

Если equals выполняется на экземпляре которого во время выполнения типа String (что имеет место в вашем коде), String «s equals выполняется (это метод перекрытие), и если передаваемый параметр также String и содержит одинаковые символы в том же порядке, он вернет true.

Вот что происходит «под поверхностью»:

public boolean contains(Object o) { 
    return indexOf(o, 0) >= 0; 
} 

public synchronized int indexOf(Object o, int index) { 
    if (o == null) { 
     for (int i = index ; i < elementCount ; i++) 
      if (elementData[i]==null) 
       return i; 
    } else { 
     for (int i = index ; i < elementCount ; i++) 
      if (o.equals(elementData[i])) // if the runtime type of o is String, 
              // String's equals is executed 
       return i; 
    } 
    return -1; 
} 
0

Вы используете то, что обычно называют «сырые» типы для вашей коллекции. Вы можете добавить все, что вам нравится, но во время выполнения это может вызвать проблемы (тип casting). См. here для обсуждения

1

Объект уже содержит определение метода equals. Поэтому, если объект, который вы вызываете, содержит on (b в этом случае), относится к классу, который не переопределяет метод equals, он будет использовать определение объекта equals.

Определение equals в Object сравнивает адрес двух объектов и возвращает true, если они равны. От https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object):

Метод equals для класса Object реализует наиболее различающееся возможное отношение эквивалентности объектов; то есть для любых непустых опорных значений x и y этот метод возвращает true тогда и только тогда, когда x и y относятся к одному и тому же объекту (x == y имеет значение true).

Если класс переопределяет метод equals (как в случае с String), тогда будет использоваться переопределяющая версия.

Смежные вопросы