Providing Java library, but hiding some classes - java

I am developing an application in Java ME that I want to provide as a library. Is there no way to hide classes that I don't want everyone to use, but is essential still in order for the library to work?
UPDATE:
I get that I can omit the public specifier, but how can I structure the library itself while developing without creating different packages? I like to view different packages as different folders simply which allows me to structure the code in a good way. However, in some cases I might need to access classes in other packages so this is rather tricky. What does packages really represents? One idea might be to create "interfaces", but these has to be declared public so that means that foreigners might also implement the interfaces intended only for some processes inside the library, correct?

For setting up your library API you'll want to protect anything you
don't want exposed. Do do this just omit the access modifier:
class fooBar {
// do stuff here
}
This will set the class access as 'default' which allows access from
within the same package as well as from any classes which subclass
fooBar.
Within your classes you will also want to lock down any access on your methods and members by marking them either private, protected or omitting the modifier so that they are 'default' as required.
private will allow access from the containing class only;
'default' (no modifier) allows from within the containing class and containing package; and
protected will allow access from within the same class, package and any subclasses.
For anything that you have exposed (public) it is also good practice to mark it as final if it's not designed to be overridden.
Basically, lock down everything as much as you can. Smaller API's are easier to use and harder to break. If you find something needs to be exposed in the future, do it in the future. It's much easier to expand an API rather than deprecate parts of it.

If Java 9 is possible, use Jigsaw modules. If not, put every class on the same package, with package-level access for hidden classes, and use Maven modules to organize them.
I've done exactly that in my project called coronata, a Wii Remote java library. Almost all classes are in package com.github.awvalenti.bauhinia.coronata, but on different modules (which appear as projects on the IDE).
Visible classes are public. They are in modules:
coronata-api
coronata-builder
coronata-demos
coronata-lib
Hidden classes have package-level acesss. They are in modules:
coronata-common
coronata-implementation-bluecove
coronata-implementation-wiiusej

You can make the classes package protected which only other classes in the same package can see.
If this isn't feasible, then you can use ProGuard to mangle the classes and hide their implementations.

Lets consider an Example:
If you have a class A, that you want to hide, and a class B, that uses the functionality of class A, then you can do this:
class B{
//Attribute and Methods
//Inner class A
class A{
//Methods and Attributes.
}
}
After doing this, you can create an Object of class A inside a method of class B and hence use it. Though the class will be hidden from other classes, it could still be used.

Yes, there is.
Simply don't declare those classes public. In other words, omit the public keyword like so:
class Internal { // rather than "public class Internal"
...
}
By default, classes are only accessible within the package where they are defined.

You need to make the classes that you don't want exposed protected. This will make them non usable from client code. Read more in the official docs

Related

Inheritance and visibility across projects

edit: I only ever used Eclipse to program Java, so all of the following (and all my knowledge on Java) is dependent on how Java is programmed in that environment.
I have two eclipse projects: Project A with class X and Project B with class Y. Class Y from project B extends class X from project A.
public class Y extends X // In short B is dependent on Project A
Class X is public and it has a nested class O.
public class X {
class O { // default access modifier
}
}
In my setup, class Y can instantiate O as long as O is not private. Meaning, even if O has a default access modifier, Y can still access O's members and variables. This is confusing to me because I thought default classes meant that foreign classes have access to it only if they shared a common package.
So the conclusion I get from this is that the default package in every project must be the same or connected in some way. Am I correct in thinking this? And if this is correct, will changes made in the package of one project be reflected on the package in the other?
And this presents the main problem I'm dealing with. I want to control access to class O such that in my example, I want Y to not be able to instantiate O. Only way I can do that now is to set the visibility of O to private, but this also restricts other classes from the same project (project A) from accessing O. I want class Y from project B (which I thought had a different package from project A) not be able to access O but some other arbitrary class from the same project as Y/O to have access to O with no problems. How can I do this?
A few different questions here so I'll enumerate them and answer individually. Also, I'll assume that by project you are referring to something like a project in Eclipse.
Am I correct in thinking this?
Correct, if you have multiple projects (e.g. JAR file build artifact Eclipse projects), each with a default package (e.g. src/main/java/Foo.java in two projects) default scope (i.e. package-private) classes will be able to see each other and their respective public, protected, and package-private methods and fields.
And if this is correct, will changes made in the package of one project be reflected on the package in the other?
Correct, assuming that the changes of the upstream project are visible to the downstream project.
How can I do this?
Strictly speaking, you can't unless, as you said, you make it private. And even then, you can circumvent it. However, what you can do is choose meaningful package hierarchies that other coders are unlikely to use. For example, names such as com.acme.myproject.subfolder are common for this reason. But somebody could still create a parallel folder in their own project and call your package-private classes. That being said, for private member classes, they could change the accessibility of that member, thereby circumventing you. While that may sound scary, if you want truly secure code, you really ought to use secure authorization to remote services. The purpose of making something package-private is to prevent it from being part of your API, rather than enforcing some true security. In fact, often this behavior is desirable. For example, suppose I have a package-private class at src/main/java/com/acme/myproj/Foo.java that I want to unit test. The Foo class is package-private because I don't want to make it part of my public API. So, I can just create src/test/java/com/acme/myproj/FooTest.java and voila, I can now execute unit tests against my package-private class Foo.
I hope that explains things.

Using shared class libraries internally, but not providing access to them in released SDK

After some research I cannot come across the best approach for this. There will be certain color classes that I would like to share amongst multiple projects. Let's call one of them EncryptedColor. Since it is used across multiple projects I don't want multiple copies of it in existence of course. Otherwise I would need to make sure that an update in one location would need to be updated everywhere. However, these classes are needed in some released SDKs that we provide to customers.
How could I design it such that I can use these classes but not provide them with the classes that they don't need access to from their SDK. I don't want useless classes to become visible and flood the smaller subset of classes that they really need to be seeing.
A couple approaches I have thought of so far but aren't quite ideal:
Try and use a doclet structure that hides the calls within the javadoc such as doclava. Javadoc has not fully implemented its own hiding mechanism yet. As I understand this doesn't keep the functions from being visible, but it was mentioned in one spot that you would need reflection to use the calls. I don't see how just the javadoc does that so I must have been missing something.
Android has designed themselves it seems to force reflection from some #hide attributes included in methods that they have in source code. But from the sounds of it, the system hides those and then uses a different jar when it is loading to make those visible at launch time. Probably not useful here.
If I were to keep shared classes in the same package name I could access default and protected members, but...then I am keeping all my classes that use these in the same package name. Not quite ideal either, but it could be done in that manner if I needed to. Might get out of hand with large quantities of shared resources.
What approaches are taken typically in situations such as these? I haven't liked my findings and thought process thus far.
Short answer : you can't hide/remove these classes as they are needed at runtime by your application.
In my opinon, you have 3 alternatives :
Change the classes access to "package private". Yes, doing that doesn't make it impossible to access them, but these classes won't be accessible directly.
Remove the classes and create an API. You want to hide the logic ? Remove it and provide it through a REST API for instance. Depending or your architecture, it could be difficult or impossible.
Create all the instance of these classes in a dynamic way, with Class.forName, using Spring or as in #Steve K answer, with Java's ServiceLoader. As a result, you will be able to remove these classes from the main jar and make them more private, in a way. Again, classes will be here but a little less accessible.
My suggestion that could work would be to implement your color classes as a service using the Java ServiceLoader
You make an interface for your color classes, and implementations can be called using the ServiceLoader class. Then you simply separate your color classes into two packages - a public package you can jar up and distribute with your SDK, and a private package for those classes you want to be internal. The ServiceLoader will find all the color classes available so long as the jar files are in your project's classpath.
For example, if your color classes (as an example) had a common interface like this:
public interface MyAppColor {
public int getRed();
public int getGreen();
public int getBlue();
public int getAlpha();
public void setRed(int red);
public void setGreen(int green);
public void setBlue(int blue);
public void setAlpha(int alpha);
public boolean isValid();
public void doSomething(Object arg);
}
Then you could have a bunch of implementing classes in a jar file, with a service descriptor file included in the jar at the path:
META-INF/services/com.my.app.MyAppColor
The text of that file is simply the list of classes in the jar that implement the interface - one per line:
com.my.app.MyPublicAppColor
com.my.app.MyEncryptedPublicAppColor
com.my.app.MyOtherPublicAppColor
etc. Then all you have to do is make a factory for instantiating the correct type, which could be as simple as this:
public class MyAppColorFactory {
private static ServiceLoader<MyAppColor> serviceLoader = ServiceLoader.load(MyAppColor.class, null);
public static MyAppColor get(String className){
if (className != null){
for (MyAppColor c : serviceLoader){
if (className.equals(c.getClass().getName())){
return c;
}
}
}
return null;
}
}
Deploying only needed code:
- Use Only The Needed Source In Development (1) (2)
Since you have an entire library and many deployments which each use different components, the easiest way to do what you suggest is to use only the sources that you need; not a single library. You can ignore the unused sources. This will only ship the needed code.
- Make The Library "Package Private"
This will allow the access only for the public components of the library and everything else will not be callable. But, it will still ship all the code.
- Create an API as a REST SDK
This will require web access, not desirable for performance code {any code really}. You will ship no sdk code with this method.
- Obfuscate the code
Easy with the correct tools. Obfuscation will change the class and method names in production code to gibberish. This will make the library basically unusable to anyone but you. This will ship all the code but it will be obfuscated
- Native API
You can compile java to machine code and use it in production or as the api. You can also create the api in a native language {not desirable}.

A Java method that can only be called by its own class or by other subclasses

I'd like my class to have a method that can only be called by itself or by its subclasses.
The closest thing is protected access, but it also allows other classes in the same package to call the method, which I don't want.
Is there a way to achieve this, or should I consider some sort of package refactoring instead?
It seems to me like private won't let subclasses use the method.
See In Java, difference between default, public, protected, and private
There is no such thing. But you can move the class in an empty package and use protected.
Short Answer: Refactor your Packages
Explanation:
The java spec considers the package relationship to be a closer relationship than that of a subclass. This is because I can extend any class as long as I import it.
If you want to be sure the method is not accessible even by subclasses outside the package, use the default visibility modifier.
Source
Stack Overflow reference
To accomplish this, put your class in a package of its own and make methods default protection. There won't be any other classes in the package to see it to call it via package access.
Consider also, that if you seal the jar that the class is in, only you control what is in a given package and have effectively locked any others from creating a class in the package that you define - no one else will be able to introduce a class into the package and break the encapsulation.
Sorry, but protected is your only choice if you want subclasses to be able to call or override a method without making it public. If you do not want other classes in the same package to have access for some reason, move your class to a new package. But if you are thinking that the package and access control keywords form some kind of DRM (i.e. digital rights management) system rather than simply a code management and class "contract" system, you are mistaken. Think of access control keywords as nothing more than documentation which the compiler has some ability to verify when other code fails to comply with the stated intent as expressed by the documentation.

Make a class extends another class at runtime

There is a library have a base class (let's call it CBase) that performs some tasks and one can create classes that extends this CBase class.
The behavior of the CBase is not enough for me, so I would like to create my own CBase class (let's call it MyCBase) that have the same methods and members but these methods don't do the same thing.
Until now everything is ok. But what blocks me is that I would like to replace CBase by MyCBase. However, I have a lot of classes that extend CBase and I don't want to change them all.
Is it possible to replace CBase by MyCBase at runtime ?
So that
public class A extends CBase {}
becomes
public class A extends MyCBase {}
Can I perform this using code enhancement ? (like we do to add methods to a class at runtime. Is it also possible to change inheritance this way ?)
Thank you for your help !
EDIT
I would like to write a plugin for a framework, this is why I would like to change inheritance at runtime. This way users of the framework can use my plugin without changing their source code (changing the inheritance of their classes from CBase to MyCBase)
EDIT 2
Is it possible to do like this: ?
CtClass cc = CtClass.forName("pkg.AClass");
cc.setSuperclass(CtClass.forName("mylib.MyCBase"));
cc.compile();
I'm not expert. Probably you could extend ClassLoader. But I highly recommend don't do it. The replacement will touch many of your classes but it will be clear in code reading and app execution.
I think there is also room for architecture improvement since you have so many classes extend CBase. People are trying to remove dependencies from other libraries or keep it really small. Because in this case you could easily switch to another library or add your own functionality.
I dont think you can change the extends of a class at runtime. I would suggest to change the extends of the objects or build an interface, which contains all the things your need
Changing all derived classes is a simple matter, provided you control their source code:
Create a new class in your project. Call it CBase, and put it in the same package as the library class.
Use the rename/move refactoring of your IDE to rename CBase to MyBase. This will have the IDE rename all references to the renamed/moved class ...
Write the code for MyBase, extending from CBase.
If you can not do this (for instance because some derived classes are in a library you do not control), you replace the implementation of CBase with your own. Simply create a class of the same package and name in your project (the classloader searches the classpath in order, and uses the first class of the proper package and name it finds). This approach however is very brittle, as the compiler can not check binary compability between the old and new version of CBase. The JVM will check this compatibility when classes are loaded, but since classes are only loaded when needed, its hard to test your changes. (Which is why I do not recommend this approach if there are other options).
You could also change the classes as they are loaded my manipulating the class file, that that's going to be even more brittle, and the compiler would allow you to use any additional features MyBase might have. ==> Definitely not a good idea.

Java API Design - Internal Design

I'm making my first API that gets data and parses it from websites. So there is a lot of network and parsing in it. I read about API's having an internal packages in which shouldn't be public; like in Javadocs. So my question is what should and shouldn't be put in the internal package. Here is my package design, I'm leaving out the non important ones.
.networkstats
.networkstats.model
.networkstats.parser
Inside networkstats package there is a class called NetworkStats. That is the main class that handles and retrieves all of the network connections. It then uses the classes inside the parser package to process the data. After it returns a Model class that holds the data inside the model package. I want to include the internal package because there will be some classes and interfaces that aren't meant to be used by the users.
For example I want to make a class the handles all of the network connections so the other classes like NetworkStats can access it. Reason I want to do that is because I don't want to copy the code in other classes when It can be in one place. Of course I don't want other users using this class so I would put it in the internal package? I would also put my parser package in the internal one too. So my main question is that do you put classes and interfaces that aren't meant to be used in the public in the internal package? I know they can still access it.
.networkStats.internal.DataManager // class that handles network connections
.networkStats.internal.parser
You might find this Java API design checklist helpful. The first section is about package design.
http://theamiableapi.com/2012/01/16/java-api-design-checklist/
Ferenc
first of all I'd like to say sub packages are the same as any other package, there is no such thing as private packages in regular java, if you want that kind of feature you'll have to use OSGi
That said, if you want to protect classes from being accessed, just remove the public on the class name, and leave public only the "API" classes, this is, the classes that your users will access (calling users the developers that uses the framework).
The more packages you create, the more "private functionality" you'll have to expose.

Categories

Resources