When to package-private (no explicit modifier) in java? - java

I have been reading the tutorial Controlling Access to Members of a Class. I am confused what might be good use case for using package-private. Because as I understand, you can always change your package declaration to whatever the package declaration of such a class and act as if that is a public class. I understand that this is not a good thing to do, but what is stopping me?

Because as I understand, you can always change your package declaration to whatever the package declaration of such a class and act as if that is a public class
Well, for one thing, the access modifiers are there to help the developer. There's always ways around them, such as via reflection for instance.
I understand that this is not a good thing to do, but what is stopping me?
Not much really!
As a developer you can however distribute your classes in sealed .jar-files which basically means that you're not letting anyone else in to your packages.
From Sealing Packages within a JAR File
Sealing Packages within a JAR File
Packages within JAR files can be optionally sealed, which means that all classes defined in that package must be archived in the same JAR file. You might want to seal a package, for example, to ensure version consistency among the classes in your software.

A couple of reasons to use package-private classes/methods:
Implementation classes that are part of a library, but not part of the library's API. This allows you to still have modular code, and acts as a sign to users of the API that the implementation classes are not for use as part of the API.
Making things available to tests. Sometimes (particularly when working with legacy code) you need to make classes or members more visible so that you can more easily unit test them. An example might be testing a class with a method that performs a resource-intensive operation that you want to override with a no-op version in your test. Another example is a class that only gets used in one place: it doesn't want to be visible to the whole app, but it needs to be unit tested.
In both cases using package-priviate visibility helps to make your code easier to use (people using it have a better idea of the scope of the class/member's intended use), while allowing you to still have modular code.

Regarding "what is stopping me":
The Java Security mechanism is stopping you, potentially. If the "target" package is sealed and signed, then Java will not allow any source other than the original to declare classes in that package.

Related

Is there any way that users of my modular library are able to access classes which have not been exported?

I'm trying to get familiar with the module system introduced in Java 9, and I would like to know the best way to leverage it.
For a library I'm writing, I would like to do the following (ignore the naming of the packages):
Expose only interfaces, simple POJO classes, and factory classes via com.myproject.api. Everything in this class can be used by the users.
Put the implementation of interfaces in com.myproject.core. Users should not be able to access anything in here.
My reasoning is that users do not need to get confused or overwhelmed by the implementation logic. Instead, they can just look at (hopefully) clean and well documentated interfaces.
However, due to the way Java packages work, it can be difficult to restrict use of certain classes without making them all package private. But I don't like putting all the classes in one package, and would rather organize them into various packages.
After reading about the module system, I believe I can do the following to achieve what I want. This is the module-info.java file:
module com.myproject {
exports com.myproject.api;
}
From my understanding, the users of my library will be able to use everything defined in the com.myproject.api package (by using require com.mypojrect.api in their own module-info file).
But is there any way that users will be able to access anything in the com.myproject.core package? I have no problem with them looking at the code (via IDE or the source code itself), but I just don't want to end up supporting classes/methods/logic which I didn't want to expose.
I'm concerned that users who don't have a modularized application or users who put my library JAR on the classpath will somehow find a way to get access to the supposed restricted package.
Please let me know if you need any other information.
A pre-JDK9 user of your library cannot exist, as you're going to use the Java Platform Module System, which is post-JDK8, and thus you're going to compile to a class version greater than 52.
Said that, your users will be able to look at the source code (if shipped), and obviously they will be able to extract your .class files.
By definition
a type in a module is not accessible to other modules unless it’s a
public type and you export its package.
The only way to gain Reflective access to your classes would be if you willingly opened them, with the
opens your.package
directive. So basically, you're covered also on the Reflection aspect.
And the opens directive exposes to Reflection only public definitions.
If you want to control Reflective access to your classes in a non-modular/pre-JDK9 environment, SecurityManager might be what you're looking for. However this requires access to the JVM configuration.

How to make a private package?

I'm doing a library. I have three packages:
Spreadsheet is the main package. The io package is an internal package for internal use. Unfortunately, the user can access to them since they are public classes.
I would like to keep this package, since it allows me to separate concepts while programming, but i would like to "hide" these classes to the end user.
What could i do?
It's good that you're asking yourself this question! I don't see much attention on this lately.
As OdsReader and OdsWriter are used only inside the Spreadsheet class, just move them inside the spreadsheet package, removing the public visibility keywork. They'll now be accessible only from the spreadsheed package's classes.
The solution proposed above, which is over-complicated for your use-case, and which is to use Java 9+ modules (or OSGi - please no!), is not really necessary here, but it's neverthless a step forward in maintaining definitions private and sealed, even to Reflection abusers.
As a side note, I see you've got an exceptions package.
I never recommend doing so, as you'll have to expose those exceptions' constructor to the users of your code, and they'll be able to instantiate them for no good reasons.
Move the exceptions inside the packages which uses them, and declare the constructor as package private.
Starting with java9, you can turn this library into a module. See this jigsaw tutorial.
Modules need to export a package in order for its public members to be accessible from other modules: Simply don't export your internal package, and it won't be visible.
You can also go with something like OSGi, a module system that predates java9. It too has this notion that there's a level beyond public (let's call it 'visible').
A final option is to use classloader shenanigans (where you for example rename your class files to some other extension during the build phase, and have a small bootstrapper in your visible package which creates a classloader that loads classes by looking in the same place as the visible API, and then load files with the alternative extension, and defineClass those into being), but that's a drastic step that introduces quite a bit of headache. I wouldn't take it unless you have excellent reasons to go down this rabbit hole.

Controlling Class Visibility in Java

My project has currently following package structure.
Here I have added a package name utils and defined all utility classes related to this module inside it. Those have been used by other packages (i.e. impl, internal), and because of that I have made classes and methods in util package public.
Because, it is public, not only classes in this module, classes in other modules can also access this and when I am coding using my IDE they are shown as coding suggestions.
I went through few research papers which describe how this can reduce the usability of the API and give a bad experience to developers who involve in the development [ref1, ref2].
I understand that java does not allow me to make classes inside util accessible to impl and internal packages and not to others.
Is it correct to put my utility classes to a package 'util'? Or should I put all classes that communicate with each other to the same package?
You are correct, something marked public becomes usable in any other package. In contrast to other languages, Java doesn't provide any control beyond that.
A simple workaround: it might be helpful to have one special package containing those public things that should be available to your external users.
Meaning: create something like com.whatever.product.api - and instruct your users that they are fine to use everything from there - but nothing else.
In other words: you make all those things public that you need to public; but you collect those things in a special place that you allow to be used by others.
It is worth mentioning though that Java9 will introduce the concept of modules, those allow you to define which of your packages should be public to users of your module. In that sense, java 9 modules allow you to distinguish between "internal" and "external" public.
Util classes are fine. Util classes are functionality that is used multiple places in a project but doesn't really belong to a specific class.
In a perfect world of OOP there wouldn't be any util classes, but it is however considered a good practice to create util classes if they do not belong to a specific class.
Your options for access modifiers are listed here:
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
There is one way to achieve what you you want, it is however concidered a very bad practice. You can change your access modifiers of util classes to protected. This will make your util classes accessible from subclasses and packages. So if a class needs access to one of the util classes, then it has to extend this util class and thereby become a subclass. I cannot stress it enought, this is a very bad practice.

Best practive for JUnit package naming?

I was trying to find some best practice for naming Java package for testing. I would be thinking something along:
Tests on:
com.example.MyClass
should be in:
com.example.test.MyClassTest
Typically I put the test classes in the same package, but under a different source root. Aside from anything else, this allows you to test members (and indeed classes) which have default visibility. Sometimes I'll even make methods which would otherwise be private, package-level to make testing easier, knowing that it will only have limited impact. This very much depends on the context in which you're developing though. (Most of my code is written in a trusted environment; I want to limit access for elegance, but I'm not worried that anyone will actively try to use a method they shouldn't. And I use an annotation to indicate the intention.)
You definitely want an easy way of separating out your test classes from your production classes, both for deployment purposes and to let you concentrate on "just the prod code" when appropriate. But I don't see any disadvantage in using the same package declaration for both tests and production code.
One of the best options is putting the tests in another source folder. This way you can easily seperate the acctual source from the tests, e.g. when building a release. Take a look at Mavens default directory layout. A propper IDE should be able to handle different source folders even without Maven.
As for the package: If you have two different source folders, you can have the test classes in the same package. This has several advantages like beeing able to access package protected members from your test or using nice plugins like MoreUnit.

Creating an invisible class in a jar

How do I create a jar in java that only one class is visible (public) to users of the jar?
I know I can omit the "public" from the declaration of a class, which makes it visible only to that package, but how do I do it in a jar with several packages, when the visibility should be public to all the classes inside the jar, but not outside of the jar?
You're basically looking for the Java counterpart of .Net's assembly-wide visibility. I'm afraid you don't have this ability within the framework of current Java. Future version of Java will offer better support for modules, which should allow something along these lines.
You'd have to include all your classes in a single Java package, and omit the "public" modifier in the class definition.
I recommend against this. If you want to indicate a class shouldn't be used by clients of a library, put it in a package named "impl" or "internal" and don't provide public documentation.
Does using protected as modifier fix this? I know it does allow access for inherited classes, but I don't know about all the other classes in the package.
Just a wild idea, but you could play around with a custom classloader that loads files from your .jar which are not recognised as classes otherwise.
For instance you could postprocess class files by encrypting them and storing with your own file extension, then loading and decrypting them from the jar by your custom classloader from the "main" class that is visible to the users of the class. (caveat; I have never tried to do something like this myself :-))
Another method (if the code base isn't too large) might be to develop your classes like normal, run your tests on the package structure and as the last step before packaging use a (perl) script to rebuild your main class by inserting all other classes as private static inner classes and rebuild that. Using this transformation as a pre-package step means you can develop in a sane structure while hiding the implementation classes in the jar.

Categories