Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:向同一项目的所有包公开公共类方法,但对其他项目公开私有类方法_Java_Oop_Design Patterns_Access Modifiers - Fatal编程技术网

Java:向同一项目的所有包公开公共类方法,但对其他项目公开私有类方法

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

我有一个库项目,它有两个包,分别是package1和package2,分别是class1和class2。class1向最终用户公开了一些公共方法。我想在class1中添加一些只有class2可以访问的实用方法。我搜索了很多,但找不到方法的任何访问修饰符,只允许在同一项目的不同包之间进行访问

是否有任何机会以任何方式实现这一目标

更新(代码示例):

包装1中的类别1:

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
实例化了2
Class1
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();