Java - Unable to access protected method of superclass extended by nested class - java

I'm new to java and getting the hang of protected visibility.
I have Class A which has protected method method1 as follows -
public abstract class A {
public A(...){}
protected void method1(){
// do something
}
Now I have another Class B which extends a different Class C. Class B has a nested static class, Class D extending Class A
public class B extends C {
public B(...){
super(...);
}
private static class D extends A {
D(...){super(...);}
}
public void method2() {
D record = new D();
record.method1(); // need to access the protected method1 of class A, which is the superclass of nested class D. Getting the error here
}
}
I get this error - method1 has protected access in Class A
Now my question is how can I access method1? I cannot change it to public in class A

You need to create a proxy method in class D as outlined below. Class D can access Class A's protected methods, but an instance of Class D can't call protected methods directly, and must have a proxy method to call the protected method of the super class.
In class D, you need to create a public getter for the method in Class A, so:
public class A {
protected void protectedMethod() {}
}
public class D extends A {
public void callProtectedMethod() {
super.protectedMethod();
}
}
final D record = new D();
record.callProtectedMethod();

Since A.method1() is protected, it is only accessible from same class/same package/child of A.
In your code, your are calling A.method1() in B, that is not accessible if B not in same package as A
The solution is using a wrapper as #Alex Ander or change modifier of A.method1() to public

Related

Java static constructor access in child class

I have two classes
package a;
public class A {
protected void doSomething() {
}
protected static class C {
protected C(int c) {
}
}
}
package b;
public class B extends A {
#Override
protected void doSomething() {
C c = new C(0); //compile error
C c2 = new C(0){}; //legal
}
}
I have read chapter 6.6.2.2. Access to a protected Constructor of JLS (https://docs.oracle.com/javase/specs/jls/se11/html/jls-6.html) but i am still confused with the explanation. What is wrong with the call of the super constructor new C(0); even if B is a child of A?
Thank you :-)
Variables, methods, and constructors, which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class.
Now, the constructor of C class is protected therefore is accessible outside the a package only by subclasses of C. But B is not a subclass of C ...
As #Amongalen pointed out, the second statement
C c2 = new C(0){};
is legal because it creates an anonymous class that extends C, therefore the protected constructor is visible here.

override static method functionality

We have class library as
class A {
public void callWorkflow() {
B b = new B();
}
}
class B {
public void callStatic() {
C.someMethod();
}
}
class C {
public static someMethod() {}
}
We are actually trying to change functionality of static method someMethod. Is there a way to solve this problem without changing call hierarchy?
You can't just Override a static method. In my opinion, remove static from the method someMethod(), then create an object of class C inside class B. Then call the method.
Class A{
public void callWorkflow() {
B b = new B();}
}
Class B{
public void callStatic(){
C c = new C();
c.someMethod();}
}
Class C{
public someMethod(){}
}
There is no way to override a static method.
That's why one of these approaches is preferred to calling static methods:
Inject another object (service) that will provide the functionality in a non-static method and call it through the injected object
Make the static method a thin wrapper that just delegates the work to some non-static object that can be configured (like in slf4j's logger)

when you extend a private class. are the public and protected members of class become private

when you extend a private class. Are the public and protected members of class become private. if not any explanation.
if you extend a nested private class, it wont change public/protected modifiers of the members. Here is an example :
public class Clazz {
private static class NestedClazz {
public int value = 123;
}
public static class NestedClazzExt extends NestedClazz {
}
}
you can now access the inherited member: value from outside
public static void main(String[] args) {
NestedClazzExt nestedClazz = new Clazz.NestedClazzExt();
System.out.println(nestedClazz.value);
}
you can create private class in side a class . We call it as Nested classe. Means a class inside a class. The Concept itself is saying that you can create private class in side another class. The private class will act like as data member to the outer class.
So, You can't extend the private class.
Based on your query I tried to prepare a simple class.
public class pvtClass {
private class As {
public String abc = "private attribute";
public void print(){
System.out.println("privateClass");
}
}
class Ab extends As{
public String ab = "extended attribute";
public void printAb(){
System.out.println("extended class");
print();
System.out.println(abc);
}
}
public static void main(String as[]){
Ab ab1 = (new pvtClass()).new Ab();
As as1 = (new pvtClass()).new As();
ab1.printAb();
as1.print();
System.out.println(as1.abc);
}
}
If you have a look at this class, I have a private class named "As" which has public attribute and public methods. I have another class named "Ab" which extends "As". I have written a main method to invoke the private attribute and methods.
below is the output for the code snippet:
extended class
privateClass
private attribute
privateClass
private attribute
There is a difference between the access of the members of a class and the access to the type itself.
public class C {
private class InnerP1 {
public void m() {
System.out.println("InnerP1.m()");
}
}
private class InnerP2 extends InnerP1 {
public void p() {
this.m();
System.out.println("InnerP2.p()");
}
}
public InnerP1 strange() {
return new InnerP2();
}
}
In this example, the interface I is visible from outside class C. The classes InnerP1 and InnerP2 are not visible from outside C. Jave itself makes not restrictions to the visibility of types you use in your public interface. The method strange() of class C returns a result of class InnerP1. Since outside of C we do not know anything about the class InnerP1 other than it is subtype of Object, the only thing we can do is use the result of strange() as an Object.
public class D {
public static void main(String[] args) {
C c = new C();
Object o = c.strange();
if(o.equals(c.strange())) {
System.out.println("Strange things are going on here!");
}
}
}
As #KnusperPudding pointed out already, the visiblity of public members is not changed, we might just not have enough knowledge of the type itself to access them.
Access to members cannot be restricted by sub-classing. When you mark a class as private then access via the class name is restricted i.e. to the same .java file, however once you have an instance of this class it can be accessed at least as easily as the super class.

Protected inner-class is NOT accessible from subclass of another package

I have the following code in Java:
package a;
public classs ClassInOtherPackage{
protected void protectedMethod(){}
protected class protectedInnerClass {}
}
package b;
import a.*;
public class MyClass extends ClassInOtherPackage{
public MyClass(){
MyClass x = new MyClass();
x.protectedMethod(); //<-- This one ok
//UPDATED: Declaration is ok
MyClass.protectedInnerClass y; //<-- This one ok
//UPDATED: Only when instantiated is not allowed, why?
y = x.new protectedInnerClass(); //<-- Not allow when instantiated.
}
}
Refer to the Java documentation:
"The protected modifier specifies that the member can only be accessed
within its own package (as with package-private) and, in addition, by
a subclass of its class in another package."
Why can't I instantiate the inner protected class as shown above?
In JLS 8.8.9
8.8.9. Default Constructor
... if the class is declared protected, then the default constructor is implicitly given the access modifier protected (ยง6.6); ...
So the implicitly declared constructor is:
protected class protectedInnerClass {
protected protectedInnerClass(){
super();
}
}
You code won't compile because the constructer is inaccessible.
The default constructor of protectedInnerClass is protected , not the class . You need to define a public constructor to your inner class :
protected class protectedInnerClass {
public protectedInnerClass () {}
}
MyClass can access the protected members of ClassInOtherPackage , but it cannot access the protected members of protectedInnerClass , since its constructor is protected hence you get such a compilation error.
As johnchen902 said the default constructor of a protected class is implicitly protected.
Protected means that only subclasses and classes within the same package can access it.
The protectedInnerClass doesn't declare a constructor thus it is implicitly protected.
MyClass is not a subclass of protectedInnerClass, thus it can not access it.
So you have to make it public or you can modify your code like this:
public class MyClass extends ClassInOtherPackage {
public MyClass() {
MyClass x = new MyClass();
x.protectedMethod(); // <-- This one ok
MyClass.protectedInnerClass y = x.new MyProtectedInnerClass();
}
protected class MyProtectedInnerClass extends protectedInnerClass {
}
}

Why have I no access to the protected field?

I am learning about access levels in java and I have created 3 classes:
In package my.inheritance
I have class A and class C
package my.inheritance;
public class A {
protected int a=15;
}
package my.inheritance;
public class C {
public static void main(String[] args)
{
A a = new A();
System.out.println(a.a);
}
}
And in another package called my.inheritance.test I have a class B trying to access protected field of int value a but the compiler complains for this!
package my.inheritance.test;
import my.inheritance.A;
public class B extends A{
public static void main(String[] args)
{
A a = new A();
int value = a.a;
System.out.println(value);
}
}
I was under the impression with protected you can access a member from a different class in a different package as long as you subclass it! Why the visibility error then ?
Every method can access protected fields of its own class, and all its parent classes. This does not include access to protected fields of another class, even if they have the corresponding base class in common.
So methods in class B can access protected fields from objects of class B, even if they were declared in A, but not from some other object of class A.
One could say that class B inherits the protected members from A, so now every B has those members as well. It doesn't inherit access to the protected members of A itself, so it cannot operate on protected members of any A but only on those of B, even if they were inherited from A.
Try:
public class B extends A
{
public static void main(String[] args)
{
B a = new B();
int value = a.a;
System.out.println(value);
}
}
You can access a only if it is in the same object.
1. protected is an access modifier which is used when you want to have an access outside the package.
2. Most people try to access the protected member of the Super class by creating and Object reference variable of the Super class, and then using dot operator to access that protected member.... But thats WRONG.
3. We get access to the inherited member of the Super class Not the direct member of the super class.
Eg:
package com.demo1;
public class A{
protected int a = 5;
}
package com.demo2;
public class B extends A{
public static void main(String[] args){
System.out.println(new B().a); // This "a" is the inherited member
}
}
4. And one more important point, This inherited "a" member in the sub-class, will be seen by the another class in the same package that of the sub-class as a private member.. So consider that another class in this package can't even see this protected memeber...
You have access to this field from B using this.a because B extends A, but in this case you are trying to access to this field througth an instance of A, this is limited by the protected access.
What you're trying to do is:
A a = new A();
int value = a.a;
Note that a.a is a qualified name, and in this case you can call it in body of a class B only if the type of the expression to the left of . is B or it's subclass.
Relevant part of JLS

Categories