Reputation: 5286
I am trying to test the following situation:
city.Main
)package castle
)castle.Guard
), and a package-private class (castle.Princess
).Here is my code:
Main.java
package city;
import castle.Guard;
public class Main {
public static void main(String[] args) {
Princess princess = Guard.getPrincessStatic();
// Error: Princess cannot be resolved to a type
Guard.getPrincessStatic().sayHi();
// Error: The type Princess is not visible
Guard guard = new Guard();
guard.getPrincess().sayHi();
// Error: The type Princess is not visible
guard.getPrincessMember().sayHi();
// Error: The type Princess is not visible
}
}
Guard.java
package castle;
public class Guard {
public Princess getPrincess() {
return new Princess();
}
public static Princess getPrincessStatic() {
return new Princess();
}
private Princess m_princess = new Princess();
public Princess getPrincessMember() {
return m_princess;
}
}
Princess.java
package castle;
class Princess {
public void sayHi() { System.out.println("Hi world"); }
}
Notice all the 4 statements in main()
are having errors.
I have done some research too. In fact i want to mimic this answer. But i don't why my codes throw errors.
Thanks for any explanations!
I intend to make the castle-Princess
package-private. I know that, by returning a package-private class out of its package, I should be prepared for errors. But why that answer works, while mine doesn't?
Upvotes: 4
Views: 4202
Reputation: 49372
Princess
class is default scoped to castle
package , so its invisible within city
package . To circumvent that :
(We can do one of the following three approaches.)
Princess
class public
and use it .package castle;
// added public modifier
public class Princess {
public void sayHi() { System.out.println("Hi world"); }
}
public interface
and let Princess
implement it and use the interface reference
instead of the class reference
. I would prefer this .castle \ IPrincess.java
// Interface definition
package castle;
public interface IPrincess {
public void sayHi();
}
castle \ Princess.java
// Implement the interface in Princess class
package castle;
class Princess implements IPrincess {
public void sayHi() { System.out.println("Hi world"); }
}
castle \ Guard.java
// Modify the Guard class
package castle;
public class Guard {
public IPrincess getPrincess() {
return new Princess();
}
public static IPrincess getPrincessStatic() {
return new Princess();
}
// for here i use Princess instead of IPrincess. (@midnite)
private Princess m_princess = new Princess();
public IPrincess getPrincessMember() {
return m_princess;
}
}
city \ Main.java
// Modify the main class
package city;
import castle.Guard;
import castle.IPrincess;
public class Main {
public static void main(String[] args) {
IPrincess princess = Guard.getPrincessStatic();
Guard.getPrincessStatic().sayHi();
Guard guard = new Guard();
guard.getPrincess().sayHi();
guard.getPrincessMember().sayHi();
}
}
Upvotes: 5
Reputation: 136022
Your example is different because your classes are in different packages and Guard and Princess are not visible from Main.
But public method can return an instance of a private class. JDK is full of examples, here is one from java.util.Arrays
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
...
private static class ArrayList<E> extends AbstractList<E> {
...
it is what you ask. The trick is that the method's return type is a public interface which the private class implements. You could do something similar.
Upvotes: 0
Reputation: 135762
The answer you are trying to mimic works because all the classes are inside the same package.
If you put UntrustworthyFriend
and Friend
in different packages (as your scenario), the same problems will arise.
Princess
can only be visible outsite it's package if public
:
Princess.java
package castle;
public class Princess {
public void sayHi() { System.out.println("Hi world"); }
}
Also, make sure to import it in Main
.
Upvotes: 1
Reputation: 13672
You are not going to be able to return a type that is privately scoped within a class. How can any external sources know what that type even IS if it's privately scope inside of another class?
This design won't even compile.
Edit:
The simple solution is to make it public and then you can use it externally outside of the package.
Upvotes: 1
Reputation: 14313
The problem lies in a very small error in the definition of your Princess class:
package castle;
class Princess {
public void sayHi() { System.out.println("Hi world"); }
}
All looks fine at first, but you're missing a public
modifier before the class name:
package castle;
//here!
public class Princess {
public void sayHi() { System.out.println("Hi world"); }
}
Without the public modifier, the princess class cannot be accessed outside of the file in which it is declared.
Upvotes: 0