在Java中,是不是可以有两个具有完全相同签名的函数,除了一个是静态的

Posted

技术标签:

【中文标题】在Java中,是不是可以有两个具有完全相同签名的函数,除了一个是静态的【英文标题】:In Java, Is it Possible to Have Two Functions with the Exact Same Signature, Except One is static在Java中,是否可以有两个具有完全相同签名的函数,除了一个是静态的 【发布时间】:2021-12-14 00:01:01 【问题描述】:

我正在编写一个类Baz<T>,其函数声明类似于以下内容:

public SomeClass1<T> foo(T);                               // Overload #1
public SomeClass1<T> foo(T, SomeClass1<T>);                // Overload #2
public SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>); // Overload #3

由于 #1 是唯一使用 this 的函数,我可以将所有其他函数设为 static

public SomeClass1<T> foo(T);
public static <T> SomeClass1<T> foo(T, SomeClass1<T>);             //#2 and #3 now static
public static <T> SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>);

但是,这会使调用不同的 foo 重载不一致。我可以简单地让#1 使用Baz(而不是this),但似乎:

baz.foo(t);

比语法糖更多:

Baz.foo(baz, t);

如果我不将 #2 和 #3 设为静态,则无法阻止类似的情况:

Baz<Bar> baz1 = new Baz<Bar>(); // Bar is any class type; replaces T
Baz<Bar> baz2 = new Baz<Bar>();

SomeClass1<Bar> sc = new SomeClass1<Bar>(baz1); // make a SomeClass1 that is somehow attached to baz1; however, SomeClass1 does NOT keep a reference to baz1

baz2.foo(new Bar(), sc); // runs and compiles just fine!

我最终尝试做的是为每个重载一个非静态和一个静态重载,其中非静态重载简单地委托给静态:

public SomeClass1<T> foo(T);                 // All non-static overloads delegate to the corresponding static overload
public SomeClass1<T> foo(T, SomeClass1<T>);             
public SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>);

public static <T> SomeClass1<T> foo(T, Baz<T>);     // Baz could be first or last argument
public static <T> SomeClass1<T> foo(T, SomeClass1<T>);            
public static <T> SomeClass1<T> foo(T, SomeClass1<T>, SomeClass1<T>);

我从重载#2、#3 及其相应的静态重载的声明中收到以下错误,将my-method-signature 替换为相应的方法签名,将my-class-name 替换为Baz&lt;T&gt;,或者我的数据类型使用:

方法 my-method-signature 的擦除与 my-class-name 类型中的另一个方法相同

问题:

    还有比我正在尝试或想要做的更好的选择吗?是否有可能完成我正在尝试的事情?如果有,怎么做? 我正在尝试做的事情(即,使语法一致,并且不可能调用具有“不匹配”SomeClass1&lt;T&gt;this 对象的方法)是否值得?

附:抱歉,帖子太长了。

【问题讨论】:

你为什么担心将静态方法设为可以是静态的?为什么不让它保持非静态并继续前进? 此链接可能会有所帮助:***.com/questions/42185449/…。另请注意,在某些情况下,使用 static 方法通常是一种反模式。尽量让事情变得简单。 我觉得你的问题相当混乱。有一次你说你想阻止baz2.foo(new Bar(), sc);,然后你继续尝试将both声明为非静态和静态foo,这根本不会阻止...... @Sweeper 我试图通过提供替代选项来防止这种情况,但仍与其他语法保持一致。写这个的时候还不知道可以用对象调用静态函数。 【参考方案1】:

是的,有一个更好的选择:什么都不做。

拥有不需要this 来完成工作的方法并没有错。这是一种实现选择,与实例履行其实现方法的约定无关。

有很多常用的设计模式都有这样的方法。以各种工厂模式为例——它们的方法有一个返回实例的契约。没有人知道或关心他们是否使用this 来完成工作。

【讨论】:

【参考方案2】:

不,你不能。

8.4.2。方法签名 如果两个方法或构造函数 M 和 N 具有相同的名称、相同的类型参数,则它们具有相同的签名 (如果有的话)(第 8.4.4 节),并且在调整 N 的形式参数类型之后 对M的类型参数,形参类型相同。

方法 m1 的签名是 a 的签名的子签名 方法 m2,如果:

m2 与 m1 具有相同的签名,或者

m1 的签名与签名的擦除(§4.6)相同 平方米。

两个方法签名 m1 和 m2 是覆盖等效的,只要 m1 是 m2 的子签名或 m2 是 m1 的子签名。

声明两个方法是编译时错误 覆盖类中的等效签名。

https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4

【讨论】:

以上是关于在Java中,是不是可以有两个具有完全相同签名的函数,除了一个是静态的的主要内容,如果未能解决你的问题,请参考以下文章

Java 方法重载与引用数组类型

Java协变式覆盖(Override)和泛型重载(Overload)

java方法简介

创建具有相同名称但不同签名的别名

在同一个类/结构中具有相同签名的相同函数?超载?

同时上传具有相同代码库但签名不同的两个版本的 apk