-1

The method: protected void removeRange(int fromIndex,int toIndex) in class ArrayList is protected, so I cannot call it on an ArrayList object, but I can call it on an object from a class that extends ArrayList, as the code below shows. However, we have classes in Java API that extend ArrayList like: javax.management.relation Class RoleList Why I cannot call removeRange() on an object of type RoleList like I did with my class: ExtendsArrayList?

public class ExtendsArrayList extends ArrayList<Integer> {
    
    public static void main (String[] args) {
        
        ExtendsArrayList list = new ExtendsArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        
        // I can call removeRange() here.
        list.removeRange(1, 3); 
        
        RoleList rl = new RoleList();
        rl.add(1);
        rl.add(2);
        rl.add(3);
        rl.add(4);
        rl.add(5);
        
        // The method removeRange(int, int) from the type ArrayList<Object> is not visible
        // Why its not visible in a class that extends ArrayList?
        //rl.removeRange(1, 3);
    }
}

EDIT: Why I should extends RoleList for this to work? RoleList extends ArrayList aromatically, why I cannot expect to call removeRange() on an object of RoleList to just work? On the other word, why ArrayList.removeRange() is not visible to an object of type RoleList when RoleList extends ArrayList, when it IS visible to an object of my class: ExtendsArrayList extends ArrayList? ExtendsArrayList is extended by me and RoleList is extended in Java API.

public class ExtendsRoleList extends RoleList {
    
    public static void main (String[] args) {
        
        RoleList rl = new RoleList();
        rl.add(1);
        rl.add(2);
        rl.add(3);
        rl.add(4);
        rl.add(5);
        
        // The method removeRange(int, int) from the type ArrayList<Object> is not visible
        // Why its not visible in when RoleList that extends ArrayList?
        //rl.removeRange(1, 3);
        
        ExtendsRoleList erl = new ExtendsRoleList();
        
        erl.add(1);
        erl.add(2);
        erl.add(3);
        erl.add(4);
        erl.add(5);
        
        // Why I should extend RoleList for this to work? Why its not visible when RoleList extends ArrayList automatically? 
        erl.removeRange(1, 3);
    }
}
blueSky
  • 649
  • 5
  • 13
  • 31
  • do you see the compile-time issue? – VedantK Jul 29 '21 at 23:56
  • Yes, this is the compile error: "The method removeRange(int, int) from the type ArrayList is not visible". – blueSky Jul 29 '21 at 23:57
  • On my side, on JDK 11, I can't call removeRange even on my own class extending ArrayList like you did for ExtendsArrayList. – Matteo NNZ Jul 29 '21 at 23:58
  • I am on Java 8 but I see the method: protected void removeRange​(int fromIndex, int toIndex), in Java 11 API, so am not sure why do you see a compile error. What's the error? – blueSky Jul 30 '21 at 00:01
  • @blueSky `removeRange has protected access` (same than yours basically). What you pasted in your answer is really all your code or did you omit something to make it easier? – Matteo NNZ Jul 30 '21 at 00:09
  • Its all the code, nothing has omitted. If you see a compile error, please share. – blueSky Jul 30 '21 at 00:13
  • @blueSky sorry, I answered you on the other comment below. I've read too fast and overlooked the `extends ArrayList` on the top of your class. I think the below answer is the explanation you're looking for. – Matteo NNZ Jul 30 '21 at 00:14

2 Answers2

1

protected means that it can be called from a subclass in the context of itself; protected does not mean that class B1 extends A can call protected methods of A on class B2 extends A.

Example:

class A {
    protected void protectedMethod() {
        //do something
    }
}

class B1 extends A { //<-- we are extending A
    public void someMethod() {
        B1 b1 = new B1();
        b1.protectedMethod(); //<-- you can call it because B1 extends A and you're in the context of B1
    }
}

class B2 { //<-- we are not extending A
    public void someMethod() { //<-- this method is exactly the same than above
        B1 b1 = new B1(); //<-- B1 is still extending A
        b1.protectedMethod(); //<-- though, you can't call the protected method anymore because you're not in the context of itself
    }
}
Matteo NNZ
  • 11,930
  • 12
  • 52
  • 89
chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • Would you please explain what you mean? If class B1 extends A, it can call the protected methods in A even if its in a different package. Also if class B2 extends A, it can call the protected methods in A. Not necessarily calling methods from B1 in B2 or vice versa. Would you please show a code example? – blueSky Jul 30 '21 at 00:05
  • 1
    @blueSky the problem is that you're not calling `removeRange(1,2)`, but you're calling `rl.removeRange(1,2)`. You're not calling the method `removeRange(1,2)` inside the source code of the class extending `ArrayList`, but you're calling it from an instance of that class as if it was a public method. Indeed, I don't get how you can possibly call `list.removeRange(1,2)` in your example without the compiler complaining for the same reason. – Matteo NNZ Jul 30 '21 at 00:08
  • @MatteoNNZ It's because he's calling from within `ExtendsArrayList` still. – chrylis -cautiouslyoptimistic- Jul 30 '21 at 00:10
  • @Matteo NNZ: you can copy/paste my code and it should work. I needed to show that I can call removeRange() on a class that extends ArrayList (ExtendsArrayList) but yet cannot call it on RoleList object when the class RoleList extends ArrayList. – blueSky Jul 30 '21 at 00:11
  • @chrylis-cautiouslyoptimistic- ah right, I had just seen the "main" method so I thought the class was defined somewhere else, didn't see it was inside the same class. – Matteo NNZ Jul 30 '21 at 00:12
  • @blueSky yes I see now, I hadn't notice that the class defining your main method was also the class extending ArrayList. That clearly explains the issue now. – Matteo NNZ Jul 30 '21 at 00:13
  • @Matteo NNZ: please note since RoleList extends ArrayList, then "supposedly" you should be able to call removeRange() on an object of type: RoleList regardless if the code is inside another class that extends ArrayList or not (like my class: ExtendsArrayList), I just wanted to show that piece of code inside the same class. – blueSky Jul 30 '21 at 00:19
  • @blueSky no, that's not how protected works. If a member/method is protected, you can call it only from inside the source code of the class extending the base class. In your example, you got it working with `ExtendsArrayList` just because your `main` method calling is inside the class. You can try to create a new class (not extending `ArrayList`) and paste your code there, you will see that your `list.removeRange(1,2)` will throw the same compile error than your `RoleList` right now. – Matteo NNZ Jul 30 '21 at 00:21
  • @blueSky No, you suppose incorrectly. You can call `removeRange` on _that_ type that extends `ArrayList` _from within that same type_ that extends `ArrayList`, not a _different_ type. – chrylis -cautiouslyoptimistic- Jul 30 '21 at 00:22
  • @Matteo NNZ: yes, of course. If I have a class that does not extend ArrayList, then I cannot call removeRange() on the object which is purely an ArrayList. But it does not explain what I am asking about RoleList b/c RoleList extends ArrayList automatically. – blueSky Jul 30 '21 at 00:25
  • 1
    @blueSky I didn't express myself well. Currently, your code `main` is inside the class `ExtendsArrayList`. Keep your class `ExtendsArrayList`, but move your `main` code inside another class. You will see that the line currently compiling `list.removeRange(1,2)`, suddenly won't compile anymore and so you should understand what chrylis wanted to explain you. – Matteo NNZ Jul 30 '21 at 00:26
  • @Matteo NNZ: I understand your point, I think I did not explain my question properly. I added an Edit to my question. – blueSky Jul 30 '21 at 00:36
  • @blueSky this answer is still the correct one. You asked "why I cannot expect to call removeRange() on an object of RoleList to just work?". Well, because as this answer states since the beginning, the method removeRange is protected and hence you can only call it inside the source code of the class inheriting. You're not inside the source code or RoleList, hence you cannot call removeRange from an instance of RoleList. However, you are inside the source code of ExtendsRoleList, and so you can call the protected method on an instance of ExtendsRoleList *inside* the source code of the class – Matteo NNZ Jul 30 '21 at 00:42
  • But RoleList extends ArrayList, what you are saying makes sense, if I had removeRange() method defined in RoleList but RoleList was not extending ArrayList. I think I don't understand the difference bet. me extending ArrayList and a class that is extending ArrayList by default in Java API. Its like we need to extend two times... – blueSky Jul 30 '21 at 00:45
  • I am not asking why erl.removeRange() works, rather why rl.removeRange() does not work when RoleList extends ArrayList. Why the need to extend again? – blueSky Jul 30 '21 at 00:49
  • @blueSky it's hard to explain this in comments :) _"why rl.removeRange() does not work when RoleList extends ArrayList"_. Because the method `removeRange()` has protected access in ArrayList. This means that you can call it _inside_ the code of the class `RoleList`, but not from an instance of `RoleList`. Since in your example you're not inside the class `RoleList`, you can't call it directly. As soon as you extend that class (or simply `ArrayList`) and then call the method _inside_ the class you just extended, then you get access to it. – Matteo NNZ Jul 30 '21 at 00:55
  • @chrylis-cautiouslyoptimistic- I've added an example to your answer to make the concept clearer to OP, I hope you don't mind – Matteo NNZ Jul 30 '21 at 01:01
  • But I can call it on an instance of ExtendsArrayList b/c I am inside the class ExtendsArrayList? Is the answer yes? "This means that you can call it inside the code of the class RoleList, but not from an instance of RoleList." That's something I did not know... Thank you for clarifying it... would you please confirm the answer "yes" above and then if you want, please post an answer, like the above comment as answer that I can accept. Previous answer is not clear at all, your comment is. – blueSky Jul 30 '21 at 01:01
0
rl.removeRange(1, 3);

You have tried to access removeRange() a protected method from the outside package (outside lang package) where it's not accesible. So the compiler is complaining about it.

list.removeRange(1, 3); 

your class extended ArrayList and thus had access to override or use protected methods directly through the protected class modifier because of inheritance.

You are invoking your object's method that it got through inheriting through parent class, and is now able to be invoked because it becomes a part of your custom subclass.

VedantK
  • 9,728
  • 7
  • 66
  • 71