What's the reason of making top-level class non-public in Java?
Let's say we have Foo.java, there could be
class Foo {
}
or
public class Foo {
}
I understand that there will be some class - visibility issues with the former example (probably it won't be visible from other packages). But anyway, are there any reasons why someone may want to do as in the first code sample?
UPD: What cons I see in the former solution: nobody cares that it's non-public. That class can be simply extended by some other public class in the same package later, then, non-public part of the class may bring you visibility/access issues.
Here is an example.
No one needs to know about existence of our ConcreteDocument.
DocumentIF.java
public interface DocumentIF {
}
ConcreteDocument.java
class ConcreteDocument implements DocumentIF {
}
DocumentFactory.java
public class DocumentFactory {
public DocumentIF createDocument() {
return new ConcreteDocument();
}
}
Typically, you make a class package-private because you don't want the class to be used outside the package. When a top-level class isn't public, it's private to the package.
Say you have a package with a number of classes that must communicate the same sort of data with one another. But this data structure is an implementation detail and so you don't want it being used by user code. Making the transfer class package private maintains this sort of package level encapsulation.
I understand that there will be some class - visibility issues with the former example (probably it won't be visible from other packages).
That seems to me to be reason enough to use it if you want to keep the class private to that one package.
Just noticed another use! It seems you can only have one public top-level class per code file, but any number of non-public top-level classes. Haven't verified it personally, but if true that could be quite useful to prevent cluttering your project folder and to group classes with related functionality that aren't needed outside of the package.
Classes without a public or protected modifier are only visible inside the package they reside. If you think of components and interfaces there is a reason for leaving out the public modifier. Let's say you have a public class MyCompontent that internally uses other classes, but does not want to publish those to the outside world (users of the component) it makes sense to leave out the visibility modifier.
It is considered good design to keep the visibility of a class to the most minimum required. The reasons that I can think of:
The class can easily change in the future without causing breakages in external packages as the external packages do not have access to the class. In this regard it might be even better to start off a class by making it a private inner class.
The class being package visible cannot be extended by classes in external packages. This again makes it easier for this class to change without causing breaking changes in external packages. If this class was not meant to be extended then it would be even better to make this final.
A public visible class becomes a part of the exported API of your library. If you are a library designer, it is better to keep your exported API as small as possible because you do not want to confuse your consumer with un-necessary classes/details. Item 1 would again hold good in this case.
The book "Effective Java" by Josh Bloch is an excellent reference for Idiomatic Java code and design.
Related
I would like to test my java code with mockito and I would NOT like to have all my methods being public.
My problem is the following, let's assume I have the following code:
package com.whatever;
public class Parent
{
public void PlayWithChild(Child child)
{
child.Hug();
}
}
package com.whatever.subpackage;
public class Child
{
public void Hug()
{
}
}
and I have the test:
package com.whatever;
import com.whatever.subpackage;
public class Test
{
#Test
public void PlayWithChild_ChildHugged()
{
//Arrange
Child mckChild = Mockito.mock(Child.class);
//Act
new Parent(mckChild).PlayWithChild();
//Assert
Mockito.verify(mckChild).Hug();
}
}
Now if I make Hug method package-accessible (removing) the 'public', then I can not access it from the test... and I don't want to put everything (Parent, CHild, and my whole testable library) to the same package, I want to organize them.
You'll need to decide what degrees of encapsulation and abstraction you want your design to have. Java doesn't have a particularly granular way of specifying which components are accessible from which other components, so you may have to express those in documentation instead of relying on the compiler to enforce them for you.
In your case, I think you should make the Hug method public; if you want to make it really clear, add corresponding Javadoc or put Child into a subpackage called "internal" to discourage its casual use.
Java's four access levels:
public access, which poses no problem to testing or mocking
protected access, which includes package access and out-of-package subclasses. Testing within the same package is easy, but you may have to create manual test doubles to access/verify protected method calls from outside the package in question.
Default or package-private access, which as you noted is easy to test/call from within the same package. From other packages, the methods don't exist in any meaningful way for calling or testing.
private methods, which can't be called or tested directly.
Why would someone make a private method in test-driven development? Easy: Because the private method is an implementation detail that doesn't need to be tested. Likewise, protected or package-private methods are implementation details that don't need to be tested outside of the package. Here, if the Hug() method is public and it calls private or package-private method FeelBetter(), then callers from other packages should go only by the public API Hug without calling or concerning themselves with implementation details like FeelBetter().
The consequence of this is to almost encourage large, overscoped packages, because that may look to be the best way to hide irrelevant implementation details from other packages and to limit the number of entry points. It's true that putting close collaborators in the same package allows small package APIs, which is a good goal. With enough classes in one package, though, this notion breaks down; luckily, it only breaks down once the package is demonstrated to be so big it merits two separate packages, at which point you can stop and think about which components are connected and which ones can be extracted into APIs of their own. This may mean widening access for certain classes/methods from package to public, which is to be expected when splitting packages. It may also imply adding accessible getters or other state-querying methods for the sake of testing, which is also to be expected when developing testable components.
For more information about how to make testable systems, and how to interact with test doubles (or real tested components), I suggest reading Martin Fowler's article Mocks Aren't Stubs.
How do I change my mistakenly c#-ish design to work with sensible access protection in java?
Here is my super class
abstract class Parent {
protected parentVariable;
protected parentMethod() {
//These methods and variables contain internal workings of my sub-classes
//to avoid repetition
// I don't want classes elsewhere in the package (that don't inherit from class) to see these.
}
}
I have sub classes that have shared internal working, which I've stuck it in the super class. It's still hidden to the other classes and usable by sub classes. Wait, no: this isn't c#, this is java.
Protected(c#) != Protected(java) ≈≈ Internal(C#).
c# protected = Access is limited to the containing class or types derived from the containing class.
java protected = Access is limited to the current package
Everything in the package can see access these. That's far too permissive for these internal workings.
How do I solve this? Do I have to bring the shared code down to the sub-classes and use "private" at the cost of code repetition? Was my use of parent classes bad design in the first place? Do I have to squirrel these inheritance trees away in new packages?
There is no access modifier that allows visibility to subclasses but not to classes of the same package.
But that's not such a big problem because classes in a given package are supposed to be "friend", cooperate, and be released all at the same time.
Even if they see some fields and methods that they shouldn't use, the other classes of the package are not part of any external API that you have no control on, and the protected methods are not accessible to the external code.
So, just document that these methods and fields shouldn't be used so that you or your coworkers don't mistakenly use them. Or put this class in its own package if you're really concerned about same-package visibility.
I am going through head into java and came across this example
interface Nose{
public int iMethod();
}
abstract class Picasso implements Nose{
public int iMethod(){
return 7;
}
}
class Clowns extends Picasso{}
class Acts extends Picasso{
public int iMethod(){
return 5;
}
}
Because nothing is declared public, doesn't that mean that none of these classes can be called from another file? I have another file
public class Of76 extends Clowns{
public static void main(String[] args) {
Nose [] i = new Nose[3];
i[0] = new Acts();
i[1] = new Clowns();
i[2] = new Of76();
for(int x = 0; x < 3; x++) {
System.out.println(i[x].iMethod()+" "+i[x].getClass());
}
}
}
So in this example class Of76 can make classes out of another file that doesn't have any public classes. I am confused on why the first file can have all those classes and why they are not in separate classes. I read that a class that is not public is private by default, and can only be called within the same class. So everything in the Nose file can only be called inside that Nose file?
When you exlude public and don't have anything else there like protected or private this is called "package protected". This should explain the differences to you: In Java, difference between default, public, protected, and private
The answer to this question is a matter of perspective.
If you are a new Java learner and you are learning language features and the object-oriented paradigm, then a reasonable answer is "you should always make classes public" because visibility restrictions matter to nobody but you. Visibility is an issue only for production code or when you are exporting an API for other clients to use. It is not unreasonable to make classes public until you know how to write good classes (I would NOT extend this advice to fields of classes, however).
However...
If you are maintaining or modifying production code -or- developing an API that you intend to export for other programmers to use, then the best answer is "you should never make classes public unless your clear intent is that your clients should be able to access your class and use it in their own client code.
Visibility is one of the most important security and encapsulation mechanisms in Java and you should never be cavalier about it in a production environment. Everything in your API should have the lowest possible visibility.
There are some important exceptions that can be imposed upon you by other API's that you may be using. For example, if you are developing a controller class for JavaFX, then in JavaFX 2.2 you are required to make your class public, whether you want to or not. Even so, these exceptions do not break the rule that "everything in your API should have the lowest possible visibility."
TL;DR: If the code you're working on will be accessed only by you, then you need never make classes anything but public. If you're working on production code, code that will become available to others, or an API that you intend to export for client use, then you should never make classes public unless it is a clearly indicated part of your design.
public MyClass this class will be visible to classes in your package and classes in other packages.
protected MyClass this class will be visible to classes in your package and only other classes that are subclasses of MyClass.
MyClass this is "default access" or "package-private" access. MyClass is visible only to classes in the same package.
private MyClass this class is not visisble to other classes except those that are in the same .class file.
Default access and Private access are considered non-exported visibility levels. Classes with these visibility levels may be freely modified by you as their implementation details are not exported as part of any API.
Public and protected access are considered exported visibility levels. Generally, once you've exported a class as part of your API you are expected to continue to support it "forever".
In C#, if I want a class to be visible to any class within that assembly (DLL), I simply scope it as internal (which is the default).
How can I do this in Java? In Java, I've noticed the default/internal scoping is package level, not JAR level. This is a problem for me, since I have a library that has several sub-packages with different responsibilities (view, controller, etc.) and can't put them in the same package.
As an example, I have two classes like com.stackoverflow.main.first.One and com.stackoverflow.main.second.Two, both of which should be able to instantiate each other.
Edit: I don't want the class to be public and visible from anyone who references it. It's an internal class only. I'm creating an API for consumption, and of primary importance to me is which classes can be seen by consumers of my JAR.
Java has no concept of library-level scoping. Make the classes public or use a factory.
To accomplish what you want, you'll have to use some mix of a factory pattern to create the classes you want to expose and leave the private classes package private. Usually, I've done this:
create the public interface for the API in a package like com.foo.bar a la public interface Foo {}
create a factory class that exposes a create method a la:
public class FooFactory{
public Foo buildFoo(){ return new FooImpl(); }
create FooImpl as a package private class - class FooImpl implements Foo{}
Document package to indicate proper usage.
It's not perfect, but until the JSR about module scoping progresses, it's probably the closest you can get in java. If you want to ensure that FooImpl doesn't get inappropriately extended, be sure it is marked final.
sounds as simple as you have to use the public access modifier.
i am developing a Java Api to do things (secret, uhhhh ;).
Is there a way to hide classes, and the internal structure of my API?
What i found until now:
Using inner classes (ugly way, i do not want to put all in on class file)
All classes in one package so that i can use the "package"-visibilty (also ugly, i need more packages)
Example:
---
package net.my.app;
//this is the Public Access
class MyPublicClass{
public void somePublicFunction(){
//access to not visibil classes
}
}
---
package net.my.app.notvisible:
//this is what i want to hide
class MyNOTPublicClass{
...
}
---
Any ideas?
Thank you!
There are two solutions to your question that don't involve keeping all classes in the same package.
The first is to use the Friend Accessor/Friend Package pattern described in (Practical API Design, Tulach 2008).
The second is to use OSGi.
Related Questions: 1, 2, 3, and 4.
Use interfaces to define what your
app does
Create a main entry point to accesses services, returning interfaces only
I wouldn't bother about actually hiding the implementation classes. You can never really hide them in Java, and those who are technically interested might just start your app with a debugger. Just provide no public constructors, for example
Regarding this comment:
Sean, would you elaborate a little
more on your answer? ...
One way to implement my second bullet point I mean using a Service Lookup class, e.g.
public class Lookup {
private static final Foo foo = new FooImpl();
public static Foo getFoo() {
return foo;
}
}
Foo is an interface, FooImpl an implementation class (which can be package private if you want to enforce that it can't be instantiated by clients)
What do you mean by 'hide'?
You can use the final modifier to stop people from extending methods and classes you don't want them to extend. If you want to stop people from decompiling your code, you can use code obfuscation and if you want to take it even further, you can use anonymous inner classes that implement interfaces.
You can try and make only your interfaces public. Have a look at the Factory Pattern.
Alternatively, you can implement you're application in OSGI.
Neither of these methods would allow you to hide the implementation completely to someone who really wanted to see it. Someone could still use a decompiler to examine you .class files, or even examine the code in memory.
If you really need to protect your implementation in this way, then a good approach would be to only allow access to your application as a remote service and host it on a secure machine.