### 基本知识

 Liquor Java 脚本，支持完整的 Java 语法及各语言版本特性（具体，看运行时版本）。脚本代码，可分为两部分：

* 代码头（用于导入类）
* 代码主体（用于构建程序逻辑。支持内部类、接口、或记录）

Helloworld：

```java
Scripts.eval("System.out.println(\"hello world\");");
```

### <mark>脚本编写提要（重要）</mark>

* 可以导入类和静态方法；但不能有包名
* 使用内部类时不要加 "public" 修饰
* 使用 CodeSpec::imports 导入表达式需要的类或静态方法；或者在代码里添加 "import" 语句
* 如果在代码里添加 "import" 语句，每个导入要独占一行，且放在代码头部。


### 支持预编译（可以缓存起来）

```java
Execable execable = Scripts.compile("System.out.println(\"hello world\");");

execable.exec();
```


### 支持所有 Java 语法特性


* (1) 支持 Java8，泛型与Lambda表达式等特性


```java
public class TestApp {
    public static void main(String[] args) throws Exception {
        Scripts.eval("""
                //::代码头
                import java.util.ArrayList;
                import java.util.List;
                
                //::代码主体
                List<String> list = new ArrayList<>(); //泛型
                list.add("c");
                list.add("java");
                
                list.stream().forEach(System.out::println); //Lamda 表达式
                """);
    }
}
```

* (2) 支持 Java11，var 等特性


```java
public class TestApp {
    public static void main(String[] args) throws Exception {
        Scripts.eval("""
                //::代码头
                import java.util.ArrayList;
                
                //::代码主体
                var list = new ArrayList<String>(); //var
                list.add("c");
                list.add("java");
                
                list.stream().forEach(System.out::println);
                """);
    }
}
```

* (3) 支持 Java17，record 等特性


```java
public class TestApp {
    public static void main(String[] args) throws Exception {
        Scripts.eval("""
                //::代码主体
                record Point(int x, int y) {}; //定义内部类、或接口、或记录
                
                Point origin = new Point(12, 34);
                System.out.println(origin);
                """);
    }
}
```

* (4) 支持 Java21，switch 模式匹配等特性

```java
public class TestApp {
    public static void main(String[] args) throws Exception {
        CodeSpec codeSpec = new CodeSpec("""
                //::代码主体
                return switch (obj) {
                     case null -> "null";
                     case String s -> "String=" + s;
                     case Number i -> "num=" + i;
                     default -> "未知对象";
                 };
                """)
                .parameters(new ParamSpec("obj", Object.class)) //声明参数
                .returnType(Object.class); //声明返回类型

        Scripts.eval(codeSpec, Maps.of("obj", "1"));
        Scripts.eval(codeSpec, Maps.of("obj", 1));
    }
}
```


### 支持内部类

```java
public class TestApp {
    public static void main(String[] args) throws Exception {
        CodeSpec codeSpec = new CodeSpec("""
                //::代码主体
                class HelloClass {
                    public String hello() {
                        return "hello";
                    }
                }
                
                HelloClass test = new HelloClass();
                return test.hello();
                """)
                .parameters(new ParamSpec("obj", Object.class)) //声明参数
                .returnType(Object.class); //声明返回类型

        Scripts.eval(codeSpec, Maps.of("obj", "1"));
        Scripts.eval(codeSpec, Maps.of("obj", 1));
    }
}
```

### 如何调试脚本？

因为是 100% 的 Java 语法。所以我们可以使用 Java 开发工具进行调试。

* 把“代码头”放到一个类的头部
* 把“代码主体”放到一个静态函数里

这样，就可以调试了。比如，把上面的 (1) 示例转面调试形态就是：

```java
//#代码头#
import java.util.ArrayList;
import java.util.List;

public class TestApp {
    public static void main(String[] args) throws Exception {
        //#代码主体#
        List<String> list = new ArrayList<>();
        list.add("c");
        list.add("java");

        list.stream().forEach(System.out::println);
    }
}
```


### 支持 JSR223 接口规范

```java
@Test
public void case1() {
    ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
    ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("liquor"); //或 "java"

    scriptEngine.eval("System.out.println(\"Hello world!\");");
}
```
