Controlling Class Visibility in Java - 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.

Related

What is basic package structure in the project for Java?

I'm trying to learn some basics of Java and Spring. Recently I came across some beginner project and one of the first steps was to create a Spring Initializr thanks to its website, where everything is clear to me. The next step was to create a basic package structure in the project: model, controller, repository, config, service.
Could someone explain me what exactly is meant by creating these packages after creating a new project? I tried to look up the information myself, but unfortunately I couldn't find an answer anywhere.
I will start by recommending reading about Packages in Java.
In a nutshell, packages are folders. They are used for storing (mainly) classes, but other entities can be stored in packages as well. For example, text files, pictures, etc. In Java, there is no hard set rule that state that only classes must be stored in packages. That said, this is typically not the way projects are structured.
One of the most important functions of packages is to provide namespace for classes. Consider two classes named Table. One is a table containing data and the other is a table used to put stuff on top of; for example a dining table. This means that Table will have to different meanings. Operating Systems will not allow for two files with the same name to exist in the same folder. Therefore, you need to put them in two folders (packages). In the code, you can break ambiguity by declaring the objects using the class' fully-qualified name. For example,
myproject.furniture.Table diningTable = new myproject.furniture.Table();
myproject.data.Table dataTable = new myproject.data.Table dataTable();
There is also access protection with packages by using default access modifier (no modifier). For example:
package myproject
class PackagePrivateClass {
// class contents omitted
}
Notice that this class is not public. In Java, this means that this class is visible to other classes in the same package only. Not even classes in sub-packages will have access.
In summary, packages provide namespace, physical organization, and access protection.
The second thing you should be familiarized with is the best practices with regards to naming your packages. Organizations tend to have packages structured with the domain first, then the main system the code is part of, then subsystems, etc. Before providing examples, here is an article about Package Naming from Oracle.
java.awt => Contains all of the classes for creating user interfaces and for painting graphics and images. AWT stands for Abstract Window Toolkit
When you see the package name, it gives developers and idea what type of classes can be found inside. This will help looking for functions when you are not familiarized with the API (which in turn will help you learning the API much faster). Imagine how hard would be to learn Java if all classes were in the same folder. Imagine how hard will be to figure out what the project does if meaningful names are not used. In the example above, it is kind of easy to figure how what to expect out of classes in the java.awt package.
I was hoping to give you more examples, but I am out of time. Maybe later I will return and write more about this.
Package is nothing but a group of classes. You want to categorize your classes basis their respective purposes. If it's just for self-learning, your package structure should be like
org.novak.sample.service.*
This package should contain all Services, not anything else.

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.

Where to put my framework classes using package-by-feature convention?

I've been reading a lot about package-by-feature naming convention. So I've decided to give it a try in a new project. However, I'm not sure how it should be named my packages that will be used by most of my classes, since I'm using a huge framework, such as Spring and Hibernate, for example.
This is how handle our Spring contexts classes:
And our database access class, the one that manages connections and so on.
I've a draft about this: using a common package for these frameworks, like:
com.company.project.common.spring
com.company.project.common.database
But I'm afraid that this still looks like package-by-layer a bit. :)
How the packages that will be accessed by my feature classes should be created ?
The common recommendation is "package by feature, not layer". What I often do is "package by feature, then layer". I also think that top-level packages should be "feature"-based (functional components, whatever). But I also like to have my layers separated into sub-packages.
From my point of view, framework-related code does not per se constitute "features" (as in "important, high-level aspects of the problem domain"), therefore package-by-feature is does not make much sense here. But still, this is important code and you need an approach to structure it.
I am normally use two approaches:
If I need to extend or augment libraries I'm using, I structure packages parallel to the package structure of the library. For instance if I'd need to implement some new number formatter for Spring, I'll probably name the package com.acme.foo.springframework.format.number, parallel to org.springframework.format.number.
However if I need to implement common base classes for layers of features, this would be probably something like com.acme.foo.common.<layer>. For instance if we have com.acme.foo.<feature>.dataaccess packages for data access layer of some feature, com.acme.foo.common.dataaccess could hold base classes for data access layers of all features.
Both approaches are used in parallel. You just have to decide whether some class is a framework or library extension (can you imagine using it outside this project?) or is it closer to the layers of your project.

When to package-private (no explicit modifier) in 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.

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