有条件地在编译时删除Java方法

前端之家收集整理的这篇文章主要介绍了有条件地在编译时删除Java方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图实现类似于C#预处理器的东西.我知道 Java不具有相同的预处理器功能,并且我们意识到有办法通过像Factory这样的设计模式来实现类似的结果.但是,我仍然有兴趣找到解决这个问题的办法.

目前,我所做的是创建一个包含几个静态最终布尔属性的类,例如以下示例:

public class Preprocessor
{
  public static final boolean FULLACCESS = false;
}

然后我以下列方式使用:

public ClassName getClassName()
{
    if(Preprocessor.FULLACCESS)
    {
        return this;
    }
    else
    {
        return this.DeepCopy();
    }
}

到目前为止这么好,这解决了我的问题(上面的例子是微不足道的,但我在其他情况下使用它是有用的).我的问题是,有没有办法放置一个整个方法的条件,所以方法本身将不可用给定正确的“预处理器”变量?例如,我想要使一个特定的构造函数仅适用于“完全访问”的包,如下所示:

public ClassName()
{
    // do things
}

if(FULLACCESS)
{
public ClassName(ClassName thing)
{
    // copy contents from thing to the object being created
}
}

再次,我知道Java作为一种语言的局限性(或设计决策),并且我知道在大多数情况下这是不必要的.实际上,我已经考虑过简单地创建这些“额外的”方法,并将它们的整个代码放在一个有条件的内容中,同时抛出一个异常,如果条件是不活动的,但这是一个非常粗略的解决方案似乎没有帮助给我的程序员,当我把这些图书馆提供给他们.

非常感谢您的任何帮助.

编辑:

为了补充这个问题,我试图这样做的原因是,通过使用异常作为解决方案,IDE实际上不会将方法显示为“可用”.然而,再次,这可能只是我对Java无知的情况.

我想要这样做的原因主要是因为我可以有多个公共接口可用,比如说,一个限制性的方法中的控制是更严格的,另外一个允许的,允许直接的属性变化.但是,我也希望能够主动从.class中删除部分代码,例如,在某些变体不可用的产品线开发方法中.

EDIT2:

此外,重要的是要注意,我也将有条件地生成文档.因此,每个编译版本的包将有自己的文档,仅包含实际可用的文档.

解决方法

这个答案部分是基于你对问题留下的评论和马克的回答.

我建议您使用Java接口来实现,这些接口只暴露出你所期望的API.当您需要限制较少的API合同时,扩展接口或创建现有界面的单独实现,以获得所需的内容.

public interface A
{
    void f();
}

以上是您的一般API.现在你想要一些特殊的额外的方法来测试A或调试它或操纵它或任何…

public interface B extends A
{
    void specialAccess();
}

此外,Java现在支持接口的默认方法实现,这可能对您有用,具体取决于实现API的方式.他们采取以下形式…

public interface A
{
    List getList();

    // this is still only an interface,but you have a default impl. here
    default void add(Object o)
    {
        getList().add(o);
    }
}

您可以在Oracle’s page about it here上阅读有关默认方法的更多信息.

在您的API中,您的普遍分发可能包括A和完全省略B,并省略提供特殊访问权限的任何实现;那么您可以为您提到的API的特殊访问版本包含B和特殊实现.这将允许普通的旧Java对象,除了一个额外的接口,也可能是一个额外的实现,代码没有什么不同.定制部分将仅在您的图书馆包装中.如果你想给某人一个“非特殊”的低访问版本,请给他们一个不包括B的jar,不包括任何可能的BI实现,可能通过单独的构建脚本.

我使用Netbeans作为我的Java工作,我喜欢让它使用它自动生成的默认构建脚本.所以如果我这样做,我在Netbeans做的,我可能会创建两个项目,一个用于基本API,一个用于特殊访问API,我将使特殊访问依赖于基础项目.那会让我有两个罐子,而不是一个罐子,但我会很好的;如果两个罐子让我足够麻烦,我将会经历上面提到的特殊访问版本的构建脚本的额外步骤.

一些直接来自Java的例子

Swing有这种模式的例子.请注意,GUI组件有一个void paint(Graphics g).图形给你一定的功能.一般来说,这个g实际上是一个Graphics2D,所以你可以这样对待,如果你愿意的话.

void paint(Graphics g)
{
    Graphics2d g2d = Graphics2d.class.cast(g);
}

另一个例子是使用Swing组件模型.如果使用JList或JComboBox在GUI中显示对象列表,则如果要随时间更改该列表,则可能不使用默认模型.相反,您创建一个具有添加功能的新模型并注入它.

JList list = new JList();
DefaultListModel model = new DefaultListModel();
list.setModel(model);

现在,您的JList模型具有通常不明显的额外功能,包括轻松添加删除项目的功能.

不仅以这种方式添加了额外的功能,而且ListModel的原始作者甚至不需要知道这个功能可能存在.

猜你在找的Java相关文章