Skip to content

Instantly share code, notes, and snippets.

@sirinath
Created December 8, 2020 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sirinath/a8facf06ccaabb481efc0d27994d9f81 to your computer and use it in GitHub Desktop.
Save sirinath/a8facf06ccaabb481efc0d27994d9f81 to your computer and use it in GitHub Desktop.
StringConcatFactory Example
//https://stackoverflow.com/questions/65139541
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.StringConcatException;
import java.lang.invoke.StringConcatFactory;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
import java.util.spi.ToolProvider;
public class Main {
public static void main(String[] args) throws Throwable {
String time = switch(LocalTime.now().get(ChronoField.HOUR_OF_DAY) / 6) {
case 0 -> "night"; case 1 -> "morning"; case 2 -> "afternoon";
case 3 -> "evening"; default -> throw new AssertionError();
};
System.out.println("Hello "+System.getProperty("user.name")+", good "+time+"!");
String tmp = "prefix \1 "+time+" \2 suffix";
invokeManually(time);
showBytecode();
}
private static void invokeManually(String time) throws Throwable {
MethodHandle mh = StringConcatFactory.makeConcatWithConstants(
MethodHandles.lookup(), // normally provided by the JVM
"foobar", // normally provided by javac, but meaningless here
// method type is normally provided by the JVM and matches the invocation
MethodType.methodType(String.class, String.class),
"Hello \2, good \1!", // recipe, \1 binds a parameter, \2 a constant
System.getProperty("user.name") // the first constant to bind
).getTarget();
// we can now use the handle to perform a concatenation
// the argument types must match the MethodType specified above
String result = (String)mh.invokeExact(time);
System.out.println(result);
}
private static void showBytecode() {
System.out.println();
ToolProvider.findFirst("javap")
.ifPresent(tp -> tp.run(System.out, System.err, "-v", "-c", Main.class.getName()));
}
private Main() {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment