Is there a way to access a different package without a public modifier?

Let's say I have packages:

com.mycomp.packone
com.mycomp.packtwo

      

Is there a way to access protected members of a class in a package from class to packtwo, but not allow public users to do so? The only way I can think of is securely accessing and using a subclass. But that just pushes the problem towards subclassing because I would like to have the same access restrictions as well.

In the context of this, we are redesigning our core API and want to make it more modular. Now everything is in one giant package. I haven't been here for this design, but I'm guessing it is because there are many protected uses out there.

+2


source to share


4 answers


Java packages are strictly limited (IMHO) in that there is no special mode for the package hierarchy and the restrictions between them. Each package is independent and the dot notation is for human eyes only. Also limited is the ability to restrict access to specific clients (as it makes me sometimes use the C ++ friendship mechanism ...)

AFAIK, this is your only option until Java 7 hopefully fixes the situation.



One thing you might consider though (if your project fits) is to use something like OGSi. This modulation and export framework allows you to do things more finely tuned than the language allows.

+1


source


The modifier protected

is your only option (JDK7 hasn't come out yet). As you said, this still allows subclasses in other packages to access protected members. You can prevent subclassing by declaring your classes as final

, but I'm not sure if this will be compatible with your use case. It is also important to keep in mind that all access modifiers in Java are just sentences and are easily circumvented by reflection.



0


source


As Asaf said, break the rules with reflection (use getDeclaredMethod on method instead of field):

package com.mycomp.packone;

public class Introvert {
    protected String secret = "TOP SECRET!";
}

package com.mycomp.packtwo;

import java.lang.reflect.Field;

public class Extrovert {
    public String talk(){
        return this.getSecret();
    }

    @SuppressWarnings("unchecked")
    protected String getSecret(){ // everybody in packtwo can call me!
        try {
            Class introvertClass = Class.forName("com.mycomp.packone.Introvert");
            Object introvert = introvertClass.newInstance();
            Field secretField = introvertClass.getDeclaredField("secret");
            secretField.setAccessible(true);
            return (String) secretField.get(introvert);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } 
    }

    public static void main(String[] args){
        Extrovert extrovert = new Extrovert();
        System.out.println(extrovert.talk());
    }
}

      

0


source


Consider redesigning your API to have "external" and "internal" APIs.

While you cannot do this with Java's native access modifiers, you can package your classes using:

package com.mycomp
package com.mycomp.internal

      

In the com.mycomp package, you publish the public APIs from which you allow "public" users; most of the time this package has more interfaces than classes.

com.mycomp.internal package is where you implement most of the interfaces found in com.mycomp. Naming a package inside effectively tells people that the classes in the package are internal to the API, and choosing depending on the internal packages may break their codes in future releases. What's more, if you can use OSGi, you can only export the com.mycomp package, which makes com.mycomp.internal effectively "hidden" from the rest of the world.

FWIW, mockito uses this packaging method for its API.

The disadvantage of this method is convention dependence.

0


source







All Articles