How to share package private data between two packages in Java?

依然范特西╮ 提交于 2019-12-06 01:38:43

问题


I have 2 Java packages, A & B. Let's say that some classes in package B want to use some classes in package A however, when a developer comes along and develops package C (or, say, application C), he/she will use my package B but I do not want him/her to be able to use the classes in A that B is using. That is to say, I want my classes in package A to be package private so that they are hidden from the application developer. However, I do want my own package B to be able to access those classes which are package private. Can this be done in Java? Do I basically just need to bite the bullet and make the classes public and just hope that the user doesn't try to use them? Or, do I need to replicate the classes that are in A inside of B?

My preference would be something that is not hack-y (i.e. I don't want to use reflection). Help?


回答1:


You can do it with JDK 8 and its Project Jigsaw. You might want to give a look to Project Jigsaw Quickstart Guide.

Unfortunately, Jigsaw is part of the JDK8, and it is not totally ready yet. It is not expected to be feature complete until January 2013 and will not be released before midyear 2013.

However, you can already compile your classes with the JDK 8 preview and make your ideas work.

In this case, your problem can be solved by dividing your application in independent modules. You could do something like:

module foo {
    exports foo;
    permits bar;
    permits baz;
}

Here the module foo can be required only by modules named bar or baz. A dependence from a module of some other name upon foo will not be resolvable at compile time, install time, or run time. If no permits clauses are present then there are no such constraints.

Not sure if alternative frameworks like OSGI, of which you can find implementations in Apache Felix and Eclipse Equinox offer some kind of functionality to implement these levels of encapsulation. It is probable that you may want to investigate a bit about that.

The problem with OSGi without the existence of Jigsaw is that whatever rules enforced by the framework can be broken by reflection, once Jigsaw is ready for public use, though, these rules will be enforced by Java itself, as you read above, at compile time, runtime and install time.




回答2:


You can do this with OSGi. Android and JDK 6 as target are not a problem in this case, there are OSGi frameworks running on Android -> e.g. see mBedded Server for Android. You can download a free non-commercial version from the link.

You have several options how to do it in OSGi, depending on what you want to achieve.

Option 1 (recommended): You can put packages A and B in one and the same bundle AB, and export only package B in the manifest of this bundle with Export-Package. Package/application C or any other "user" app can import package B and use it. And it cannot use and doesn't even see package A, because it is internal for the bundle AB. You don't need any special declarations or dependencies on Java level; this will work with ANY Jva version, because the modularity and the separate bundle spaces are part of the OSGi basics and don't depend on the latest Java version or smth.

Option 2: If for some reason you want packages A and B separated in different bundles, you can have them so, you'll export and import the packages in the manifest and then control which bundle has the right to import which package by using Permissions (see OSGi Permission and Conditional Permission services). However, this is more complicated to realize.

Option 3: You can also put package A in a Fragment bundle and allow it to attach to the bundle containing B. In this way B will have access to package A, but at the same time you'll be able to update package A separately during runtime if you want. Since packages in fragments are treated as private for the host bundle (in this case host is the bundle containing package B), Bundle C won't see A. It will only see what is exported by Bundle B.

Since you are not that familiar with OSGi, I will recommend to start witl Option 1 and then later if needed you can upgrade your approach to Option 3 if you want.

@Edwin Dalorzo : It is definitely not true that the rules in OSGi can be broken by reflection. Bundles have separate classloaders in OSGi. You can reflect from Bundle C as much as you won't for the classes A and the only thing you'll get is a ClassNotFound exception - believe me, I have seen it enough times ;)



来源:https://stackoverflow.com/questions/10989881/how-to-share-package-private-data-between-two-packages-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!