如何在 Java 中实现抽象静态方法?

2023-12-28

关于无法包含静态抽象 Java 方法存在许多问题。还有很多关于此问题的解决方法(设计缺陷/设计强度)。但我找不到任何针对我将很快说明的具体问题的信息。

在我看来,创建 Java 的人以及相当多使用 Java 的人并不像我和其他许多人那样将静态方法视为类函数或属于该类的方法并且不针对任何对象。那么还有其他方法来实现类函数吗?

这是我的例子:在数学中,group是一组可以使用某种操作*以某种合理的方式彼此组合的对象 - 例如,正实数在正常乘法下形成一个群(x * y = x × y),并且整数集形成一个群,其中“乘法”运算是加法(m * n = m + n).

在 Java 中对此进行建模的一种自然方法是为组定义一个接口(或抽象类):

public interface GroupElement
{
  /**
  /* Composes with a new group element.
  /* @param elementToComposeWith - the new group element to compose with.
  /* @return The composition of the two elements.
   */
  public GroupElement compose(GroupElement elementToComposeWith)
}

我们可以为上面给出的两个例子实现这个接口:

public class PosReal implements GroupElement
{
  private double value;

  // getter and setter for this field

  public PosReal(double value)
  {
    setValue(value);
  }

  @Override
  public PosReal compose(PosReal multiplier)
  {
    return new PosReal(value * multiplier.getValue());
  }
}

and

public class GInteger implements GroupElement
{
  private int value;

  // getter and setter for this field

  public GInteger(double value)
  {
    setValue(value);
  }

  @Override
  public GInteger compose(GInteger addend)
  {
    return new GInteger(value + addend.getValue());
  }
}

然而,群体还有另一个重要的属性:每个群体都有一个单位元- 一个元素e这样x * e = x对全部x在组中。例如,乘法下正实数的单位元是1,加法下整数的单位元是0。在这种情况下,为每个实现类提供一个方法是有意义的,如下所示:

public PosReal getIdentity()
{
  return new PosReal(1);
}

public GInteger getIdentity()
{
  return new GInteger(0);
}

但这里我们遇到了问题——方法getIdentity不依赖于对象的任何实例,因此应该声明static(事实上​​,我们可能希望从静态上下文中引用它)。但如果我们把getIdentity方法进入接口然后我们不能声明它static在界面中,所以不能static在任何实现类中。

有什么方法可以实现这个getIdentity方法:

  1. 强制所有实现的一致性GroupElement,这样每次执行GroupElement被迫包括一个getIdentity功能。
  2. 表现静态;即,我们可以获得给定实现的恒等元素GroupElement无需实例化该实现的对象。

条件(1)本质上是说“是抽象的”,条件(2)是说“是静态的”,我知道static and abstract在 Java 中不兼容。那么语言中有一些相关的概念可以用来做到这一点吗?


本质上,您所要求的是能够在编译时强制执行类定义具有特定签名的给定静态方法。

在 Java 中你实际上无法做到这一点,但问题是:你真的需要这样做吗?

假设您当前选择实现静态getIdentity()在你的每个子类中。考虑到您实际上并不需要此方法,直到您use当然,如果您尝试使用它但它没有定义,您will收到编译器错误提醒您定义它。

如果您定义了它但签名不“正确”,并且您尝试以与定义它不同的方式使用它,您也将收到编译器错误(关于使用无效参数调用它,或返回类型问题等)。 )。

由于您无法通过基类型调用子类静态方法,因此您always必须明确地调用它们,例如GInteger.getIdentity()。因为如果你尝试调用编译器已经会抱怨GInteger.getIdentity() when getIdentity()未定义,或者如果您使用不正确,您实际上会获得编译时检查。当然,您唯一缺少的是强制定义静态方法的能力,即使您从未在代码中使用它。

所以你已经非常接近了。

你的例子是一个很好的例子,解释了what你想要,但我会挑战你想出一个例子,其中有一个关于缺少静态函数的编译时警告是必要的;我能想到的唯一接近的事情是,如果您正在创建一个供其他人使用的库,并且您想确保您不会忘记实现特定的静态函数 - 但对所有子类进行适当的单元测试也可以在编译时捕获它(你无法测试getIdentity()如果它不存在)。

注意:查看您的新问题评论:如果您要求能够call给定一个静态方法Class<?>,你本身不能(没有反射)——但你仍然可以获得你想要的功能,如中所述乔瓦尼·博塔的回答 https://stackoverflow.com/a/22459257/616460;您将牺牲编译时检查来换取运行时检查,但获得使用身份编写通用算法的能力。所以,这实际上取决于您的最终目标。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Java 中实现抽象静态方法? 的相关文章

  • 在 Java 8 中将对象追加到列表并返回结果?

    有没有一种方法可以将对象附加到列表并以功能性非命令方式在一行中返回结果 如果原始列表也不应该被改变 你会怎么做 Java 8 是允许的 我已经知道如何将两个列表连接到一行中 Source https stackoverflow com a
  • 使用 google-api-java-client 的 2 足 OAuth

    有谁知道如何将 2 legged OAuth 与 google api java client 一起使用 我正在尝试访问 Google Apps 配置 API 以获取特定域的用户列表 以下不起作用 HttpTransport transpo
  • 向 JList 添加滚动条? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何将 JList 添加到 JScrollPane 把你的JList in a JScrollPane JScrollPane scrol
  • Maven 2 未运行 Junit 4 测试

    我在确保运行 Junit4 测试时遇到问题 同样的问题也被报告在https stackoverflow com questions 2021771 sort newest sort top https stackoverflow com q
  • 阶级等级制度中频繁的贬低总是邪恶的吗?

    据我所知 如果在类层次结构中频繁使用向下转型是没有好处的 我同意这一点 但是这条规则有哪些例外情况 如果有的话 这就是我的图形编辑器设计的薄弱之处 我有两个层次结构 其中几何图形层次结构与图形基元分离 像这样 public class Ge
  • 在 SWT 中单击鼠标触发事件?

    在SWT中 对于MouseListener接口 可用的方法有mouseUp mouseDown and mouseDoubleClick 如何根据用户点击触发事件 我们可以通过结合来做到这一点mouseUp and mouseDown 但没
  • Tomcat - 多个 webapps 文件夹

    是否可以有多个文件夹来放置要部署的应用程序 这些是如何定义的 是否可以将一个文件夹限制为仅是 domain com 的应用程序 而不是其他域 Thanks 看一眼conf server xml
  • 整数与 int 比较

    我是新来的java 我现在正在学习非原始整数类型java 我知道以下比较无效并引发编译错误 String str c Char chr c if str chr return true 上面的代码片段给了我 Test java lineNu
  • “未找到 JAVA 路径。请检查 JAVA 是否已安装。”初始化 RSelenium 时出错

    我正在尝试启动一个 RSelenium 会话到 webscrape 但是 当运行此代码时 driver lt rsDriver browser c chrome chromever 76 0 3809 126 port 4444L 我收到此
  • 在 JavaFX 中更改 ListView 字体大小

    我想知道如何更改 JavaFx 中的列表视图项目文本字体大小 每行文本的大小会有所不同 我尝试使用细胞因子属性 但我不知道如何使用它 有人可以帮我吗 类似的问题在这里 如何更改JavaFX中ListView的字体大小 https stack
  • 为什么java(>=7版本)不支持运行没有main方法的程序? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 class WithoutMain static System out println Without main class Sy
  • java:如何设置全局线程ID?

    是否有可能为线程设置唯一ID 在分布式系统中 线程是在许多不同的机器上创建的 例如通过 RMI 我需要它来创建日志消息 根据我的研究 我知道可以使用 log4j mdc ndc 来完成 但只能在单线程中完成 我的问题是 在创建线程时必须设置
  • Elasticsearch NodeBuilder 与 TransportClient

    对于其他 Elasticsearch 开发人员来说 这可能是一个非常简单 而且愚蠢 的问题 这两者之间有什么区别 我正在从 Java Web 应用程序连接到远程 Elasticsearch 服务器 到目前为止我一直在使用 Transport
  • 将 XML 从网站解析到 Android 设备

    我正在启动一个 Android 应用程序 它将解析来自网络的 XML 我创建了一些 Android 应用程序 但它们从未涉及解析 XML 我想知道是否有人对最佳方法有任何建议 这是一个例子 try URL url new URL your
  • 将字符串转换为字符并按降序排序(ascii)

    我正在创建一个程序 该程序将使用户输入整数 一个接一个 存储在数组中并按降序显示整数 该程序还要求用户输入一个字符串 使用以下命令将其转换为字符string toCharArray 我已经正确地按降序显示整数 问题是我不知道如何按降序显示字
  • Wildfly 10.1 消耗所有核心

    我们最近将银行应用程序从 java 1 6 升级到 1 8 将 jboss 4 x 升级到 wildfly 10 1 我们观察到 java 消耗了机器上可用的所有核心 10 有人可以告诉是什么原因吗 通常情况下 jboss 4 x 的最大
  • 找出该月第一个星期日/星期一等的日期

    我想在java中检测每个月第一周 第二周的第一个星期日 星期一的日期 我怎样才能实现它 我已经检查了 java 中的 Calendar 类和 Date 类 但无法找到解决方案 所以请帮助我解决这个问题 Calendar calendar C
  • 有没有办法处理Java堆空间异常[重复]

    这个问题在这里已经有答案了 我正在寻找将文件输入流转换为大文件 文件大小为 100MB 并且抛出 java lang OutOfMemoryError Java Heap space import java io FileInputStre
  • Spring Boot中服务接口类的用途

    我的问题是关于接口类的使用 我对 Spring 还很陌生 所以如果这过于简单 请耐心等待 首先 当您可以在 BoxService 中声明 find all 时 这里拥有 IBoxService 接口有什么意义 其次 在控制器中如何使用IBo
  • 将 JSON 发送到 Spring MVC 控制器

    我正在尝试将 JSON 发送到 Spring MVC 控制器 在 Spring MVC 方面 一切都配置正确 下面是代码 但似乎没有运行

随机推荐