Java:向同一项目的所有包公开公共类方法,但对其他项目公开私有类方法
我有一个库项目,它有两个包,分别是package1和package2,分别是class1和class2。class1向最终用户公开了一些公共方法。我想在class1中添加一些只有class2可以访问的实用方法。我搜索了很多,但找不到方法的任何访问修饰符,只允许在同一项目的不同包之间进行访问 是否有任何机会以任何方式实现这一目标 更新(代码示例): 包装1中的类别1:Java:向同一项目的所有包公开公共类方法,但对其他项目公开私有类方法,java,oop,design-patterns,access-modifiers,Java,Oop,Design Patterns,Access Modifiers,我有一个库项目,它有两个包,分别是package1和package2,分别是class1和class2。class1向最终用户公开了一些公共方法。我想在class1中添加一些只有class2可以访问的实用方法。我搜索了很多,但找不到方法的任何访问修饰符,只允许在同一项目的不同包之间进行访问 是否有任何机会以任何方式实现这一目标 更新(代码示例): 包装1中的类别1: package com.example.package1; public class Class1 { // This
package com.example.package1;
public class Class1 {
// This method should only be accessed by Class2, cannot made it public for
// every class
void performUtilityOperation() {
// internal utility
}
// other public methods...
}
包装2中的类别2:
package com.example.package2;
import com.example.package1.*;
public class Class2 {
Class1 class1;
public void setClass1(Class1 class1) {
this.class1 = class1;
}
public void doSomeOperation() {
this.class1.performUtilityOperation(); // here this method is not
// accessible if not public
// do some other operations
}
// other public methods
}
没有办法实现这一点(C++中没有什么代码<朋友>代码>,如果你是从这里来的话)。尽管受保护的成员可以通过扩展类从不同的包访问,如下所示:
package1
public Class1{
protected method();
}
Class2扩展了Class1
,因此即使Class2位于不同的包中,method()
也可以在Class1
中看到
package2
public Class2 extends Class1{
public otherMethod(){
method(); // is visible here
}
}
Class3
不扩展Class1
,因此method()
将不可见
package2
public Class3{
public otherMethod(){
method(); // not visible here
}
}
在我看来,这是在Class1中隐藏方法所能达到的最远距离。我将以下解决方法放在一起,以确保只有指定的包才能访问某些方法:
public class Reserved {
private static Package p = AccesserA.class.getPackage();
public void doSomething() throws ClassNotFoundException {
if (p.equals(Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()).getPackage())) {
System.out.println("Access granted");
} else {
System.out.println("Access denied");
}
}
public static void doSometingElse() throws ClassNotFoundException {
if (p.equals(Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()).getPackage())) {
System.out.println("Access granted");
} else {
System.out.println("Access denied");
}
}
}
如您所见,您指定Package p
作为允许访问的包。在方法调用doSometing()
或doSometingElse()
时,将对照允许的包检查调用类的包。如果相等,则打印授予的访问
,否则打印拒绝访问。您可以创建一个实现此功能的抽象类,每个需要受限访问的类都可以简单地扩展它并提供允许的包。它也适用于静态方法
让我们创建两个类,它们将尝试访问保留的
方法:
package a.b.c;
public class AccesserA {
public void tryAccess() throws ClassNotFoundException {
Reserved res = new Reserved();
res.doSomething();
}
}
及
主要内容:
这将产生以下产出:
Access granted
Access denied
Access denied
您可以使用default
方法向Class1
添加public
嵌套接口,这些方法在Class1
中调用各自的包访问方法,并在Class2
中实现该接口,这样只有Class2
才能访问Class1
的包访问方法通过这个界面(对不起!)
此时最好显示代码
Class1
我为该方法添加了一些哑打印实现,以表明它被正确调用
package package1;
public class Class1 {
int i;
public Class1(int i) {
this.i = i;
}
// Utility method only for Class2
void performUtilityOperation() {
System.out.println(i);
}
public interface Mediator {
default void performUtilityOperation(Class1 c1) {
c1.performUtilityOperation();
}
}
// other public methods...
}
接口定义了一个default
方法,该方法给定Class1
的实例,调用该实例的相应方法。我对封闭类和接口方法使用了相同的名称,但它们可以不同
请注意,该接口必须是公共的
本身,以便Class2
可以看到它来实现
Class2
实现该接口允许访问其默认方法。由于Class2
持有Class1
的实例,因此它(将)用于接口方法的所有调用中。接口将操作委托给Class1
实例
UserClass
我在自己的包中添加了这个类,作为实例化类和调用各种方法的地方。我不确定在你的情况下打算怎么做,但是整理细节应该不是问题
package user;
import package1.Class1;
import package2.Class2;
class UserClass {
public static void main(String[] args) {
Class1 clazz1Int3 = new Class1(3);
Class1 clazz1Int4 = new Class1(4);
Class2 c2 = new Class2();
c2.setClass1(clazz1Int3);
c2.doSomeOperation();
c2.setClass1(clazz1Int4);
c2.doSomeOperation();
// clazz1Int3.performUtilityOperation(); // The method performUtilityOperation() from the type Class1 is not visible
}
}
我用一个不同的int
实例化了2Class1
s,以便于区分它们。然后,我使用您给定的方法设置Class2
中的Class1
引用,并调用Class2
中的public
(向用户公开)方法。该调用在其内部通过Mediator
接口调用Class1
中的不可访问(不可见)实用程序方法
请注意,访问Class1
包外的实用程序方法的唯一方法是实现Mediator
(不能从Mediator
本身调用它,因为不能实例化接口)。因为只有Class2
能做到这一点(如果有的话,您可以控制其他哪些类也能做到),所以只有它能在Class1
的包之外访问它
运行上述程序的输出是
3
4
为什么使用嵌套接口?
实际上,您不必将接口作为嵌套接口—它取决于您的总体结构。它可以驻留在自己的编译单元中,但与Class1
位于同一个包中,因此(包访问)实用程序方法可见。作为嵌套接口的优点是,现在实用程序方法实际上可以是私有的
(或受保护的
),因此甚至不能在其包中访问
我提到这一点是因为你具体说明了
我想在class1中添加一些只有class2可以访问的实用方法
但不清楚您的意思是“只有class2可以访问class1包之外的内容”还是“只有class2可以访问整个包”。您让实用程序方法包访问,因此它提示了第一个选项,但我不确定
还有一个设计考虑“这是放置此接口的正确位置吗?”,但我不知道-你可以。嵌套接口通常遵循与嵌套类相同的设计注意事项,因此您必须依赖它们
最后说明
如果不明显,那么这种方法比扩展类更可取,因为这样会限制继承,而实现接口在这方面是“免费的”。如果您甚至不想让用户看到该方法,则必须创建一个facade(公共接口)并仅公开该facade。不要让用户直接使用实现类
这通常是通过使用工厂或工厂方法+(如果您愿意)使所有的
package package2;
import package1.Class1;
public class Class2 implements Class1.Mediator {
Class1 class1;
public void setClass1(Class1 class1) {
this.class1 = class1;
}
public void doSomeOperation() {
performUtilityOperation(class1);
}
// other public methods
}
package user;
import package1.Class1;
import package2.Class2;
class UserClass {
public static void main(String[] args) {
Class1 clazz1Int3 = new Class1(3);
Class1 clazz1Int4 = new Class1(4);
Class2 c2 = new Class2();
c2.setClass1(clazz1Int3);
c2.doSomeOperation();
c2.setClass1(clazz1Int4);
c2.doSomeOperation();
// clazz1Int3.performUtilityOperation(); // The method performUtilityOperation() from the type Class1 is not visible
}
}
3
4
public class Class1 implements Interface1 {
private Class1() {}
public static Interface1 create() { return new Class1(); }
// This method is not visible through Interface1
public void performUtilityOperation() {
// internal utility
}
}
Interface1 class1_instance = Class1.create();
((Class1) class1_instance).performUtilityOperation();