Значение "this" в этом коде?

 public boolean contains(Object o) {
    for (E x : this)
        if (x.equals(o))
            return true;
    return false;
}

Может ли кто-нибудь сказать мне, что в этом коде означает "this". Могу ли я написать его без этого и как?

Ответ 1

Здесь this представляет объект, по которому вызывается текущий метод. Например, если у вас есть a.contains(x), то внутри contains метод this вернет ссылку на тот же объект, что и в ссылочной переменной a.

Поскольку вы можете использовать this in for-each, это означает, что метод contains помещается в класс, который реализует интерфейс Iterable<E>, потому что for-each может выполнять итерацию только:

  • массивы вроде String[] array = ...; for(String s : array){...}
  • экземпляры классов, которые реализуют Iterable<E> как List<String>, где мы можем написать for(String s : list){...}

Чтобы избежать this, вы можете явно добавить свой параметр метода класса, который содержит этот метод, например

public boolean contains(YourClass yc, Object o) {

//and use that parameter in loop instead of `this`

    for (E x : yc)
        if (x.equals(o))
            return true;
    return false;
}

но это означает, что вам нужно будет вызвать такой метод способом a.contains(a,x), поэтому ему нужно дважды повторить a (не говоря уже о том, что это может позволить нам передать другой экземпляр нашего класса, чем a, как a.contains(b,x)).

Чтобы избежать этого повторения, мы можем сделать метод contains static, который позволит вызвать его через YourClass.contains(a,x). Но таким образом нам нужно отказаться от одного из основных понятий ООП - полиморфизма - поскольку он не работает с методами static.

Компилятор решает его с помощью первого решения, поэтому он компилирует наши методы, как они были бы написаны (и мы на самом деле МОЖИМ писать методы таким образом) как

public boolean contains(YourClass this, Object o) {
//                      ^^^^^^^^^^^^^^
    ...
}

Тогда, когда мы пишем a.contains(x), он компилируется так, как если бы мы вызывали a.contains(a,x).

Ответ 2

this - это объект класса, который содержит ваш метод contains(). Он ссылается на объект этого класса, для которого выполняется этот метод.

Помещая это после : расширенного цикла for, означает, что класс, содержащий этот метод, должен реализовывать Iterable<E>, поскольку расширенный цикл for может использоваться для итерации по массивам или экземплярам классов, которые реализуют Iterable. Это означает, что ваш класс может выполнять итерацию по некоторой коллекции элементов E. E, вероятно, является типичным параметром типа.

Чтобы написать ваш метод без this, вам нужно будет указать ссылку на какой-либо альтернативный объект, который реализует Iterable<E>, но я не вижу смысла делать это.

Ответ 3

Что именно означает this в этом коде?

Это всегда ссылка на текущий экземпляр. Я предполагаю, что ваш класс реализует Iterable<T> интерфейс и переопределяет метод Iterator<T> iterator().

Цикл - это просто синтаксический сахар для расширенного оператора for. Согласно спецификации (§14.14.2.):

for ({VariableModifier} UnannType VariableDeclaratorId : Expression)
    Statement

Тип выражения должен быть Iterable или тип массива (§10.1), или возникает ошибка времени компиляции.

Если тип Expression является подтипом Iterable, тогда перевод выглядит следующим образом.

Если тип Expression является подтипом Iterable<X> для некоторого аргумента типа X, то пусть I - тип java.util.Iterator<X>; в противном случае пусть I будет сырым типом Iterator.

Усиленный оператор for эквивалентен основному выражению формы:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    {VariableModifier} TargetType Identifier = (TargetType) #i.next();
    Statement
}

Обычно класс реализует Iterable, чтобы предоставить пользователю API возможность разрешить итерацию по внутренней коллекции, скрывающей фактическую реализацию.

Могу ли я написать его без этого и как?

  • Используйте логику, написанную для внутреннего итератора.
  • Используйте реализацию базовой коллекции (если она и она подходит).
  • Выберите один из вариантов, упомянутых выше, и перепишите в стандартный for.

Ответ 4

Ключевое слово this - это просто ссылка на текущий объект.

Вот пример, как можно использовать this:

public class Person {
    public final String name;

    public Person(String name) {
        // name = name; 
        // which one is an argument, and which one is class field? 
        // by default, both are reference on argument

        // using "this" to access class field
        this.name = name;
    }

    public void copyFields(Person other) {
        // current object reference is the same as other object reference 
        // in other words "this" and "other" are the same instances 
        // example: 
        // Person p1 = new Person("a");
        // Person p2 = p1; // p2 is now pointing on the same memory address
        //                 // as p1, so both are pointing on the same object
        //                 // stored in memory.
        // p1.copyFields(p2);
        if (this == other) { // copying from self? useless...
            return;
        }
        this.name = other.name;
    }
}

Все, что реализует интерфейс Iterable, имеет метод, который возвращает экземпляр Iterator, который неявно используется циклом foreach для перебора элементов, удерживаемых объектом. Итератор имеет методы hasNext(), который возвращает true, если есть другой объект в итерируемом контейнере относительно текущего положения и next(), который возвращает next object или throws NoSuchElementException, если нет следующего объекта (последнее обращение hasNext() вернуло false).

Вот простой пример реализации Iterable с помощью методов contains:

public class Customer extends Person implements Iterable<Item> {
    private final List<Item> list = new LinkedList<>();
    public final String name;

    public Customer(String name) {
        this.name = name;
    }

    public void add(Item item) {
        list.add(item);
    }

    // implementing iterable interface

    @Override
    public Iterator<Item> iterator() {
        return list.iterator();
    }

    // some contains implementations

    public boolean contains1() {
        for (Item item : this) { // customer implements Iterable = OK
            if (o.equals(item)) {
                return true;
            }
        }
        return false;
    }

    public boolean contains2() {
        for (Item item : list) { // list implements Iterable = OK
            if (o.equals(item)) {
                return true;
            }
        }
        return false;
    }

    public boolean contains3(Object o) {
        for (Iterator<Item> iter = iterator(); iter.hasNext();   ) {
            Item item = iter.next();
            if (o.equals(item)) {
                return true;
            }
        }
        return false;
    }

    public boolean contains4(Object o) {
        for (Iterator<Item> iter = list.iterator(); iter.hasNext();   ) {
            Item item = iter.next();
            if (o.equals(item)) {
                return true;
            }
        }
        return false;
    }

    public boolean contains5(Object o) {
        Iterator<Item> iter = iterator(); 
        while (iter.hasNext()) {
            Item item = iter.next();
            if (o.equals(item)) {
                return true;
            }
        }
        return false;
    }

    public boolean contains6(Object o) {
        Iterator<Item> iter = list.iterator();
        while (iter.hasNext()) {
            Item item = iter.next();
            if (o.equals(item)) {
                return true;
            }
        }
        return false;
    }

    public boolean contains7(Object o) {
        return list.contains(o);
    }
}

Ответ 5

Методы определены в classes, а не в objects.

Но они (обычно) вызывается из objects.

Методы - как они определены в classes - не знают заранее, какой объект будет их называть.


Итак, существует механизм (реализуемый скрытым параметром this), с помощью которого объект - при вызове метода - тайно передает адрес себя параметру this.

(В других языках программирования могут использоваться другие имена, как Me или self.)

Ответ 6

Я бы поместил его в пункты для вас

  • Когда мы создаем новый экземпляр класса, то его нестационарные методы и нестатические поля-члены являются его частью. Мы обращаемся к этим методам и полям с помощью оператора ..

  • Все поля нестатического метода или члена имеют доступ к this. Ключевое слово this просто является ссылкой на текущий объект, по которому этот метод выполняется.

  • Любой класс, который реализует интерфейс Iterable, может использоваться с расширенным For-Loop.

  • Расширенный цикл for использует синтаксис

for (Object object : objectOfIterableType)

Если класс, реализующий интерфейс Iterable, параметризован, предположим его E. то это то, что вам нужно в вашем коде.

    for (E x : this)
  1. Это означает, что текущий класс имеет поведение, являющееся итерабельным, и может быть повторен в коллекции элементов, которые он хранит. Вышеуказанный оператор будет выполняться для каждого элемента в коллекции элементов типа E, представленного текущим объектом, указанным ключевым словом this. На каждой итерации x будет отображаться элемент из содержащихся в нем элементов.