Java “makeConcat​;”方法如何实现以及通过直接调用API使用的“StringConcatFactory”中的“makeConcatWithConstants”?

Java “makeConcat​;”方法如何实现以及通过直接调用API使用的“StringConcatFactory”中的“makeConcatWithConstants”?,java,string,dynamic,string-concatenation,invokedynamic,Java,String,Dynamic,String Concatenation,Invokedynamic,我相信自从java9以来,字符串连接已经使用StringConcatFactory实现 既然这是作为Java中的API提供的,那么方法makeConcat是如何实现的​和makeConcatWithConstants?到目前为止,我还没有找到任何不同使用方法的例子。另外,makeConcat中的String name,MethodType-concatType参数是什么​和makeConcatWithConstants和参数String recipe,对象。。。常量在MakeContatWith

我相信自从
java9
以来,字符串连接已经使用
StringConcatFactory
实现


既然这是作为Java中的API提供的,那么方法
makeConcat是如何实现的​StringConcatFactory
中通过直接调用API使用code>和
makeConcatWithConstants
?到目前为止,我还没有找到任何不同使用方法的例子。另外,
makeConcat中的
String name
MethodType-concatType
参数是什么​
makeConcatWithConstants
和参数
String recipe
对象。。。常量
MakeContatWithConstants中
的意思和应该传递给它们的内容对我来说不是不言而喻的。

您链接的文档中指出,“这些方法通常用作引导方法…以支持字符串连接功能”,这意味着,编译器使用它们来准备进行字符串连接——换句话说,程序员不打算使用它们(正如我所记得的,它们基本上创建了一种(lambda)方法来进行连接)

使用它的简单方法是:使用
+
操作符连接字符串,并让编译器完成这项工作。如果您真的想直接使用这些方法(为什么?这并不是那么简单),请使用连接创建一个类,并使用反编译器检查生成的Java代码


另请参见:(不是100%相关,而是最后一句)

您不应该直接调用此API。该类被设计为为为
invokedynamic
指令提供引导方法,因此其API直接用于该用例,而不是直接调用

但它是详尽的:

参数
  • lookup
    -表示具有调用者访问权限的查找上下文。与
    invokedynamic
    一起使用时,虚拟机会自动将其堆叠起来
  • name
    -要实现的方法的名称此名称是任意的,对于此链接方法没有任何意义。与
    invokedynamic
    一起使用时,这由
    invokedynamic
    结构的
    名称和类型提供,并由VM自动堆叠
  • concatType
    -呼叫站点的预期签名参数类型表示串联参数的类型;返回类型始终可从分配。与
    invokedynamic
    一起使用时,这由
    invokedynamic
    结构的
    名称和类型提供,并由VM自动堆叠
我补充的重点

请注意,JVM通常是如何根据
invokedynamic
字节码指令自动提供所有参数的。在此上下文中,它是一条指令,使用一些参数并生成一个
字符串
,将此引导方法称为知道如何执行操作的实体

无论出于何种原因,当您想要手动调用它时,您必须执行以下操作

String arg1=“你好”;
字符arg2='';
字符串arg3=“StringConcatFactory”;
MethodHandle mh=StringConcatFactory.makeConcat(
MethodHandles.lookup(),//通常由JVM提供
“foobar”,//通常由javac提供,但在这里没有意义
//方法类型通常由JVM提供,并与调用匹配
MethodType.MethodType(String.class、String.class、char.class、String.class))
.getTarget();
//我们现在可以使用句柄来执行连接
//参数类型必须与上面指定的MethodType匹配
字符串结果=(字符串)mh.invokeExact(arg1、arg2、arg3);
系统输出打印项次(结果);
您可以对多个字符串串联重复使用
MethodHandle
,但您的字符串绑定到引导过程中指定的参数类型

对于普通字符串连接表达式,每个表达式在引导期间都会链接到一个句柄,该句柄与固定数量的子表达式及其编译时类型相匹配

很难想象直接使用API比编写
arg1+arg2+arg3
等更有好处的场景


bootstrap方法允许指定除可能更改的参数之外的常量部分。例如,当我们有了代码

String time=switch(LocalTime.now().get(ChronoField.HOUR/u-OF-DAY)/6){
案例0->“晚上”;案例1->“上午”;案例2->“下午”;
案例3->“晚间”;默认->抛出新断言错误();
};
System.out.println(“Hello”+System.getProperty(“user.name”)+”,good“+time+”!”;
我们有几个常量部分,编译器可以将这些常量部分合并为一个字符串,使用占位符
\1
表示必须插入动态值的位置,因此
recipe
参数将是
“Hello\1,good\1!”
。另一个参数,
常量
,将不使用。然后,相应的
invokedynamic
指令只需要在操作数堆栈上提供两个动态值

为了使等效的手动调用更有趣,我们假设系统属性
user.name
是不变的,因此我们可以在引导调用中将其作为常量提供,使用占位符
\2
引用它,并生成一个只使用一个动态参数的句柄,时间字符串:

MethodHandle mh=StringConcatFactory.makeConcatWithConstants(
MethodHandles.lookup(),//通常由JVM提供
“foobar”,//通常由javac提供,但在这里没有意义
//方法类型通常由JVM提供,并与调用匹配
MethodType.MethodType(S)