如何隐藏公共方法?

Posted

技术标签:

【中文标题】如何隐藏公共方法?【英文标题】:How to hide a public method? 【发布时间】:2011-10-08 18:22:19 【问题描述】:

我的静态机器中有一个方法,该方法仅在我的应用程序首次启动时使用一次。该方法需要公开,但我仍然希望它隐藏。有没有办法使用注解或其他东西来隐藏项目其余部分的方法?

【问题讨论】:

也许只是把它命名为明目张胆的名字——比如 OnlyUseThisOnStartup(); 你为什么希望它既是public又是hidden?换句话说,这对你有什么好处? 如果方法被第二次调用,是否让方法抛出异常? 它究竟应该在哪里可见和隐藏在哪里?也许default 可以吗?如果它是初始化程序,只需将其放入 static 块中。 @Randy & Mannimarco - 这两个我都可以,这是最简单的解决方案,我只是好奇是否有一个微妙的解决方案。 【参考方案1】:

另一种解决方案:您可以将其设为 private 并使用反射创建 invokeHiddenMethod(String methodName, Object ... args) 方法。

【讨论】:

【参考方案2】:

一旦你声明了公共方法,它就成为你的类契约的一部分。您无法隐藏它,因为所有班级用户都希望此方法可用。

【讨论】:

【参考方案3】:

嗯...您想要一个私有方法,但想在外部访问它?

尝试通过反射来做到这一点。 http://download.oracle.com/javase/tutorial/reflect/index.html

【讨论】:

【参考方案4】:

您不能隐藏公共方法(除非您可以将其声明为私有)。但是,您可以放入一个子类,并且只让对象的用户知道超类的类型,即:

class A 
   //Externally visible members


class B extends A 
   //Secret public members

然后你实例化类B,但只让类型A被其他人知道......

【讨论】:

不要通过反射破解你的方式。如果你诉诸这种虐待,它会卷土重来并困扰你的余生...... 这不是反射黑客。这是一个合法的 OOP 设计。 是的,这是对我自己的帖子的评论。我将简单地建议反对其他人在此页面上提出的反射黑客攻击。 其实我发现这个建议是最有用的。虽然问题是关于如何隐藏公共方法,但其意图可能是如何保持方法在内部可访问,而外部世界不会知道它们。但是,您始终可以定义一个接口而不是一个仅包含用于外部访问的方法的类。【参考方案5】:

您可以使用包级别而不是公共。这样它只能由您的应用程序调用。

【讨论】:

【参考方案6】:

你说你的公共方法只在应用启动时使用一次。

也许您可以将方法公开,但在第一次调用后让它什么都不做?

【讨论】:

【参考方案7】:

有一个(非)关键字级别包级别可见性。您不使用 public、protected 或 private,而是什么都不使用。

这将使该方法或类对包中的类和其他人可见,但会给您一定程度的隐私。你可能想看看What is the use of package level protection in java?。

【讨论】:

【参考方案8】:

我见过很多 Java 程序员做这样的事情:

public static void main(String args[]) 
      new MyClass();

所以基本上他们只创建了一个类的对象。如果有一种方法应该只运行一次,我想这种方法可以实现。您的方法将从构造函数内部调用。但是由于我不知道你的应用是如何工作的,有什么限制,所以只是一个想法。

【讨论】:

【参考方案9】:

如果一个方法是公开的,它就不能被隐藏。您可能真正在寻找的只是一种限制访问调用方法的方法。还有其他方法可以达到类似的效果。

如果您的状态机所做的某些事情“仅在我的应用程序首次启动时使用一次”,这听起来很像那些可能在构造函数中发生的事情。尽管这取决于这些任务的复杂程度,但您可能不想在构建时这样做。

既然你说你的状态机是静态的,那它也是单例吗?您也许可以使用Singleton Pattern。

public class SimpleStateMachine 

  private static SimpleStateMachine instance = new SimpleStateMachine();

  private SimpleStateMachine() 
      super();
      System.out.println("Welcome to the machine");  // prints 1st
  

  public static SimpleStateMachine getInstance() 
      return instance;
  

  public void doUsefulThings() 
      System.out.println("Doing useful things");  // prints 3rd
  

下面是这个 Singleton 客户端的一些代码:

public class MachineCaller 

    static SimpleStateMachine machine = SimpleStateMachine.getInstance();

    public static void main(String... args) 
        System.out.println("Start at the very beginning");  // prints 2nd
        machine.doUsefulThings();
    

请注意,SimpleStateMachine 实例直到您的类第一次被访问时才会构建。因为它在MachineCaller 客户端中声明为static,所以算作“首次访问”并创建实例。如果您确实希望您的状态机在应用程序启动时执行其中一些初始化任务,请记住这一点。

因此,如果您不想将状态机类变成真正的单例...您可以在第一次访问该类时使用static initialization block 执行一次性任务。看起来像这样:

public class SimpleStateMachine 

    static 
        System.out.println("First time tasks #1");
        System.out.println("First time tasks #2");
    

    public SimpleStateMachine() 
        super();
        System.out.println("Welcome to the machine");
    

    public void doUsefulThings() 
        System.out.println("Doing useful things");
    

当我们讨论它时,既然你提到它是一个状态机......Head First Design Patterns 这本书对State Pattern 做了一个很好的、易于理解的处理。如果您还没有,我建议您阅读它。

【讨论】:

【参考方案10】:

这样做的惯用方法是使用接口来限制方法的可见性。

例如,假设您有以下课程:

public class MyClass 
    public void method1() 
        // ...
    
    public void method2() 
        // ...
    

如果您想限制项目的某些部分只能看到method1(),那么您要做的就是在接口中描述它,并让类实现该接口:

public interface Method1Interface 
    public void method1();


...

public class MyClass implements Method1Interface 
    public void method1() 
        // ...
    
    public void method2() 
        // ...
    

然后,您可以通过选择将类作为MyClass 引用或Method1Interface 引用来限制方法的可见性:

public class OtherClass 
    public void otherMethod1(MyClass obj) 
        // can access both obj.method1() and obj.method2()
    
    public void otherMethod2(Method1Interface obj) 
        // can only access obj.method1(), obj.method2() is hidden.
    

这种方法的一个好处是它也可以很容易地扩展。例如,假设您现在还想独立控制对method2() 的访问。您需要做的就是按照与Method1Interface 相同的方式创建一个新的Method2Interface,并让MyClass 实现它。然后,您可以以与method1() 完全相同的方式控制对method2() 的访问。

这与@MathiasSchwarz's answer 中提倡的方法类似,但更加灵活:

由于 Java 不支持多重继承,Mathias 的技术无法实现上一段中描述的独立访问控制。 不需要继承关系也允许在设计类层次结构时更加灵活。 对原始类的唯一更改是添加implements Method1Interface,这意味着它是一个非常低影响的重构,因为MyClass 的现有用户不必更改完全没有(至少在选择将它们更改为使用 Method1Interface 之前)。

【讨论】:

以上是关于如何隐藏公共方法?的主要内容,如果未能解决你的问题,请参考以下文章

我应该测试私有方法还是仅测试公共方法? [关闭]

匿名对象 封装(private)this关键词构造方法

C++ - 导出 C++ 库公共部分的正确方法

Java封装 概述

如何对除 api 网关之外的所有人隐藏我的公共微服务?

如何使用 ProGuard(或任何其他方式)隐藏库 Jar 中的公共类?