Skip to content

Instantly share code, notes, and snippets.

@wkgcass
Created October 21, 2023 16:44
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 wkgcass/6388da63eb1ea858e21717171d8efa68 to your computer and use it in GitHub Desktop.
Save wkgcass/6388da63eb1ea858e21717171d8efa68 to your computer and use it in GitHub Desktop.
JDK 21 String Template Bug
import java.util.function.*;
class JDBC {
void transaction(Consumer<ConnectionW> f) {
f.accept(new ConnectionW());
}
<T> T transaction(Function<ConnectionW, T> f) {
return f.apply(new ConnectionW());
}
}
class ConnectionW {
SQL prepare() {
return new SQL();
}
}
class SQL implements StringTemplate.Processor<PreparedStatementW, RuntimeException> {
public PreparedStatementW process(StringTemplate template) throws RuntimeException {
System.out.println(template.fragments());
return new PreparedStatementW();
}
}
class PreparedStatementW {
void execute() {
System.out.println("Here I am!");
}
}
void main() {
var jdbc = new JDBC();
jdbc.transaction(conn -> {
var name = "a";
var age = 100;
conn.prepare()."""
insert into "test_user" ("name", "age") values (\{name}, \{age})"""
.execute();
});
}
/*
> javac --source 21 --enable-preview Bad00Main.java
Picked up JAVA_TOOL_OPTIONS: -Duser.language=en
Bad00Main.java:36: error: processor type cannot be a raw type: prepare
conn.prepare()."""
^
Note: Bad00Main.java uses preview features of Java SE 21.
Note: Recompile with -Xlint:preview for details.
1 error
*/
import java.util.function.*;
class JDBC {
void transaction(Consumer<ConnectionW> f) {
f.accept(new ConnectionW());
}
<T> T transaction(Function<ConnectionW, T> f) {
return f.apply(new ConnectionW());
}
}
class ConnectionW {
SQL prepare() {
return new SQL();
}
}
class SQL implements StringTemplate.Processor<PreparedStatementW, RuntimeException> {
public PreparedStatementW process(StringTemplate template) throws RuntimeException {
System.out.println(template.fragments());
return new PreparedStatementW();
}
}
class PreparedStatementW {
void execute() {
System.out.println("Here I am!");
}
}
void main() {
var jdbc = new JDBC();
jdbc.transaction(conn -> {
var name = "a";
var age = 100;
var sql = conn.prepare();
sql."""
insert into "test_user" ("name", "age") values (\{name}, \{age})"""
.execute();
});
}
/*
> javac --source 21 --enable-preview Bad05Main.java
Picked up JAVA_TOOL_OPTIONS: -Duser.language=en
Bad05Main.java:37: error: processor type cannot be a raw type: prepare
sql."""
^
Note: Bad05Main.java uses preview features of Java SE 21.
Note: Recompile with -Xlint:preview for details.
1 error
*/
> java -version
Picked up JAVA_TOOL_OPTIONS: -Duser.language=en
openjdk version "21.0.1" 2023-10-17
OpenJDK Runtime Environment (build 21.0.1+12-29)
OpenJDK 64-Bit Server VM (build 21.0.1+12-29, mixed mode, sharing)
> javac -version
Picked up JAVA_TOOL_OPTIONS: -Duser.language=en
javac 21.0.1
import java.util.function.*;
class JDBC {
void transaction(Consumer<ConnectionW> f) {
f.accept(new ConnectionW());
}
/*
* <T> T transaction(Function<ConnectionW, T> f) {
* return f.apply(new ConnectionW());
* }
*/
}
class ConnectionW {
SQL prepare() {
return new SQL();
}
}
class SQL implements StringTemplate.Processor<PreparedStatementW, RuntimeException> {
public PreparedStatementW process(StringTemplate template) throws RuntimeException {
System.out.println(template.fragments());
return new PreparedStatementW();
}
}
class PreparedStatementW {
void execute() {
System.out.println("Here I am!");
}
}
void main() {
var jdbc = new JDBC();
jdbc.transaction(conn -> {
var name = "a";
var age = 100;
conn.prepare()."""
insert into "test_user" ("name", "age") values (\{name}, \{age})"""
.execute();
});
}
import java.util.function.*;
class JDBC {
void transaction(Consumer<ConnectionW> f) {
f.accept(new ConnectionW());
}
<T> T transaction(Function<ConnectionW, T> f) {
return f.apply(new ConnectionW());
}
}
class ConnectionW {
SQL prepare() {
return new SQL();
}
}
class SQL implements StringTemplate.Processor<PreparedStatementW, RuntimeException> {
public PreparedStatementW process(StringTemplate template) throws RuntimeException {
System.out.println(template.fragments());
return new PreparedStatementW();
}
}
class PreparedStatementW {
void execute() {
System.out.println("Here I am!");
}
}
void main() {
var jdbc = new JDBC();
jdbc.transaction((ConnectionW conn) -> {
var name = "a";
var age = 100;
conn.prepare()."""
insert into "test_user" ("name", "age") values (\{name}, \{age})"""
.execute();
});
}
import java.util.function.*;
class JDBC {
void transaction(Consumer<ConnectionW> f) {
f.accept(new ConnectionW());
}
<T> T transaction(Function<ConnectionW, T> f) {
return f.apply(new ConnectionW());
}
}
class ConnectionW {
SQL prepare() {
return new SQL();
}
}
class SQL implements StringTemplate.Processor<PreparedStatementW, RuntimeException> {
public PreparedStatementW process(StringTemplate template) throws RuntimeException {
System.out.println(template.fragments());
return new PreparedStatementW();
}
}
class PreparedStatementW {
void execute() {
System.out.println("Here I am!");
}
}
void main() {
var jdbc = new JDBC();
jdbc.transaction((Consumer<ConnectionW>) conn -> {
var name = "a";
var age = 100;
conn.prepare()."""
insert into "test_user" ("name", "age") values (\{name}, \{age})"""
.execute();
});
}
import java.util.function.*;
class JDBC {
void transaction(Consumer<ConnectionW> f) {
f.accept(new ConnectionW());
}
<T> T transaction(Function<ConnectionW, T> f) {
return f.apply(new ConnectionW());
}
}
class ConnectionW {
SQL prepare() {
return new SQL();
}
}
class SQL implements StringTemplate.Processor<PreparedStatementW, RuntimeException> {
public PreparedStatementW process(StringTemplate template) throws RuntimeException {
System.out.println(template.fragments());
return new PreparedStatementW();
}
}
class PreparedStatementW {
void execute() {
System.out.println("Here I am!");
}
}
void main() {
var jdbc = new JDBC();
jdbc.transaction(conn -> {
var name = "a";
var age = 100;
SQL sql = conn.prepare();
sql."""
insert into "test_user" ("name", "age") values (\{name}, \{age})"""
.execute();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment