-5

How to change the object of the class itself from inside itself? I have one class like this:

public class AdvancedArrayList<T> extends ArrayList<T>

And I want to assign a new object to itself. But, I am unable to do that. Just see this code:

AdvancedArrayList<T> abcd = this; // works fine
this = abcd; // ERROR: variable expected

enter image description here

And this is my entire class:

public class AdvancedArrayList<T> extends ArrayList<T> {

    public void reverse(){
        Collections.reverse(this);
    }

    public void removeDuplicates(){
        ArrayList<T> wordDuplicate = new ArrayList<>();
        ArrayList<T> tempList= new ArrayList<>();


        for (T dupObject : wordDuplicate) {
            if (!tempList.contains(dupObject)) {
                tempList.add(dupObject);
            }
        }
        this = tempList;
    }
}

So, how can I change the object of the class itself?

Sambhav Khandelwal
  • 3,585
  • 2
  • 7
  • 38
  • 8
    You cannot. Why do you exactly want this? – MC Emperor Jun 06 '22 at 16:31
  • Even if you could do what you've proposed, it would effectively be a no-op as you already did `abcd=this`, so the following `this=abcd` is equivalent to `this=this`. Also keep in mind the [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle) – Rogue Jun 06 '22 at 16:35
  • @Rogue actually no. I will edit the content in the list. – Sambhav Khandelwal Jun 06 '22 at 16:35
  • @MCEmperor i need it because i am adding a `removeDuplicates` method in the class. So, when the duplicates are filtered in a temp list, I want to assign it to the object – Sambhav Khandelwal Jun 06 '22 at 16:36
  • 1
    When you assign a list reference to another list variable, e.g. `List something = abcd`, they are _the same object_. If you modify one, you modify the other. In all honesty, I would avoid inheritance for this solution. – Rogue Jun 06 '22 at 16:37
  • But @Rogue, how can I update the list inside that object because it asks me for my custom class, not the list it extends to. – Sambhav Khandelwal Jun 06 '22 at 16:39
  • Why not copy the elements into the AdvancedArrayList? Am I missing something? It would be very helpful if you shared the whole `AdvancedArrayList()` class. – MehranB Jun 06 '22 at 16:43
  • 5
    I'm not quite sure I follow your last comment. Can you update your question to include the relevant information surrounding what you're really doing? Also be wary of the [XY problem](https://xyproblem.info/) (a common pitfall for anyone). – Rogue Jun 06 '22 at 16:43
  • @Sambhav.K You might want to look at https://stackoverflow.com/questions/7979623/why-is-assignment-to-this-not-allowed-in-java – Progman Jun 06 '22 at 16:54
  • `ArrayList` is not meant to be inherited. If you want to write your own list collection, extend `AbstractList`. Your custom list can then use composition to delegate to its inner list. – knittl Jun 06 '22 at 17:34

2 Answers2

1

Your #removeDuplicates method is attempting to mutate the list object it belongs to (known by this, within this class), and as such should actually make those modifications to the list itself (rather than a copy). Note as well, that by iterating your newly-made list wordDuplicate, the for loop will not actually execute (since there are no values inside the list). I would personally keep track using a Set (namely, HashSet with a roughly O(1) lookup, aka nearly constant-time), while taking advantage of the Iterator#remove method:

public void removeDuplicates() {
    Set<T> seen = new HashSet<>();
    Iterator<T> itr = this.iterator(); //similar to the mechanics behind for-each
    while (itr.hasNext()) { //while another element can be found
        T next = itr.next(); //get the next element
        if (!seen.add(next)) { //#add returns "true" only if it was not in the Set previously
            itr.remove(); //if it was previously in the set, remove it from the List
        }
    }
}

Note as well, that the semantics you are describing nicely fit the definition of a Set, which is a collection of items that do not contain duplicates. There are varients of Set (i.e. LinkedHashSet) which also allow linear traversal of the elements, based on insertion-order.

For a simpler, non-iterator solution, you could also do a "dirty swap" of the elements after your calculation, which would be similar to what you attempted to achieve via this = list:

public void removeDuplicates() {
    Set<T> seen = new LinkedHashSet<>(); //to preserve iteration order
    for (T obj : this) { //for each object in our current list
        seen.add(obj); //will only add non-duplicates!
    }
    this.clear(); //wipe out our old list
    this.addAll(seen); //add back our non-duplicated elements
}

This can be quicker to write, but would be less performant than the in-place removal (since the entire list must be wiped and added to again). Lastly, if this is a homework problem, try to avoid copy-pasting code directly, and instead write it out yourself at the very least. Merely working towards a solution can help to solidify the information down the line.

Rogue
  • 11,105
  • 5
  • 45
  • 71
  • But, it could be optimised this way also: `Set seen = new LinkedHashSet<>(this); this.clear(); this.addAll(seen);` – Sambhav Khandelwal Jun 07 '22 at 16:19
  • 1
    This is true, but note that it would not really be "optimized" for the same reasons. It's shorter to write, but longer to run. I also purposefully avoided any compound statements in my answer so I could explain each step o/ – Rogue Jun 07 '22 at 16:19
0

It's not possible in Java. this cannot be reassigned. Why (and when) do you need to re-assign an object from within itself?

When you have code such as obj.replace(otherObj) with an imaginary implementation of void replace(Object other) { this = other; }, then why not simply write obj = otherObj to update the reference?


Further clarifications after comments:

ArrayList is not meant to be inherited. If you want to write your own list collection, extend AbstractList. Your custom list can then use composition to delegate to its inner list.

knittl
  • 246,190
  • 53
  • 318
  • 364