奇怪的Java强制类型转换语法使用&

6

实际上,这个问题与lambda不直接相关,而是涉及使用边界的转换,因此标记为重复的问题没有提供答案。你可以在这里找到答案:How should I cast for Java generic with multiple bounds?

最近我参加了一个软件工艺会议,在讨论的例子中,我遇到了这种类型的转换,它似乎自Java 8以来就是有效的Java。

Object aTest = (String & CharSequence) "test";

我的问题是:这个成语背后的含义是什么,它对我们到底有什么作用?举例的人无法解释,我也没有找到任何提及它的内容(我甚至不知道它的名称)。
我需要在Oleksandr的答案之外再回答一个问题,因为这个问题已经被标记为重复,因此被锁定了。
同时,我想通过一个(虚构的)使用案例来说明这个想法。
假设我们有一个通用方法 foo(),它只有一个参数,并且类型参数有两个上限(分别是 ComparableSerializable)。
public static <T extends Comparable & Serializable> void foo(T t) {
    System.out.println(t);
}

进一步假设,我们有一个类AClass,它实现了ComparableSerializable接口。
public class AClass implements Comparable, Serializable {
    @Override
    public int compareTo(Object other) {
        return 0;
    }
}

进一步假设一个编造的情景,我们有一个类型为`AClass`的对象`instance`,它被赋值给了一个类型为`Object`的变量。
Object instance = new AClass();

如果在代码的另一个地方,我们想要将 instance 传递给 foo(),并且我们不知道 instance 的动态类型(即 AClass),我们可以使用特殊的转换语法,在 instance 上放置一个“隐形眼镜”,以使调用起作用:

foo((Comparable & Serializable) instance);

实际上,这个特殊性并不在于cast语法,而是在于类型的声明方式。这种类型声明被称为交叉类型


2
Java对类型参数支持多重边界 - Elliott Frisch
是的,我知道类型边界,但这里没有涉及到类型参数。 - Nico
1
实际上这就是正在发生的事情。它在使用lambda ->符号时非常有用。 - Elliott Frisch
艾略特,你能给我指一个例子吗? - Nico
https://dev59.com/VmYq5IYBdhLWcg3weAaj#14469627 - Elliott Frisch
SortedSet<String> set = new TreeSet<>((Comparator<String> & Serializable) (a, b) -> a.length() - b.length()); 没有强制转换,TreeSet将不会是可序列化的,因为它的比较器不是。 - JB Nizet
1个回答

4
这是一个包含类型列表的强制转换运算符,与Java语言规范相关。
(ReferenceType {AdditionalBound}) Expression  =>  (String & CharSequence) "test";

其中AdditionalBound的定义如下:

... & InterfaceType

我大致理解了这个问题,但能否提供一个使用案例呢?

这个问题和它的答案描述了一个实际的使用案例。例如,为了使一个lambda表达式可序列化,你可以编写以下代码:

Consumer<String> consumer = (Consumer<String> & Serializable) System.out::println;

感谢@assylias的贡献。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接