首页 · ← SuperJ 手册 中文|EN

语言参考(Java → SuperJ)

这是一份面向 SuperJ 程序编写者的参考,不是教程。它假设你已经会 Java,只覆盖差异点:哪些原样保留、哪些移除、哪些改变、哪些新增。入门 walkthrough 见 快速开始;构建工具见 构建系统

SuperJ 读起来像 Java,跑起来像 C。它不是 Java 的子集 — 它保留高效的部分,丢掉妨碍可预测原生性能的部分,并加入 Java 无从应对的系统级能力。


1. 与 Java 相同的部分

如果你会写 Java,你在 SuperJ 中写的大部分东西都一样:


2. 从 Java 中移除的部分

每一次移除都换来可预测性或消除一类 bug。存在的替代方案列在下方。

移除项原因替代方案
线程、Thread 生命周期、Runnable 线程创建设计上单线程 — 确定性进程 + 共享 mmap + 全序事件流(SEDA)扩展。Runnable/SAM 接口仍作为普通类型保留,只是不再线程化。
synchronizedvolatilewait/notify/notifyAlljava.util.concurrent无内存模型,无管程无。参见 并发
Lambda / 闭包隐藏的捕获机制,不可预测的分配:: 方法引用 — 唯一的一等函数语法。无捕获。
自动装箱 / 拆箱隐藏分配;无包装类原始类型不能作为泛型类型参数(List<int> 是编译错误)。使用原始类型特化集合(IntArrayListInt2IntMap、…)。
反射、ClassLoader一切在编译期已知静态解析。instanceof/转型仍然有效(vtable + type_id)。
非静态内部类隐藏的外围实例引用仅静态嵌套类。匿名类允许,但不捕获局部变量/参数/外围实例。
受检异常噪声;实践中不被强制所有异常均为非受检。throws 允许但被忽略(仅作文档)。
finalize() / destroy() / Destroyable在 arena 下是空操作Arena 回收;对原生资源使用显式 close()/free()/zeroize()。参见 内存安全
JPMS 模块仅包package a.b.c; ⇔ 目录路径。
带标签的 break/continue复杂性用标志位重构,或抽取为方法。(注意:带标签 break/continue 保留在 §1 中 — 不同于 Java 的模式匹配变体。)
switch 模式匹配 / 箭头标签复杂性仅经典冒号形式 case V:
用户自定义注解(@interface无消费者(无反射、无 APT)仅内建 @Override/@Test/@Ignore

3. 与 Java 不同的部分

这些特性仍然存在,但语义不同。习惯了 Java 的话,这里是你会绊倒的地方。

new 是 arena 作用域的(无 GC)

没有追踪式垃圾回收器。new 从一个 arena 分配:

作用域是词法的,不是动态的:一个 new 归属于它被在其内的那个 arena。你从 arena 块内调用的方法仍然使用全局 arena,除非它自己开了一个块。

Node createNode(int v) {
    return new Node(v);          // 全局 arena — 可安全返回
}

void process() {
    arena temp {
        Buffer buf = new Buffer(1024);  // 在 temp 中
        Node n = createNode(5);         // 在全局中(createNode 没有 arena 块)
        outer = buf;   // OK:逃逸分析把 buf 放置到比 temp 存活更久的地方
    }                    // temp 释放:buf 仍有效,n 仍有效
}

一个超越其 arena 寿命的值会被放置到一个确实比它存活更久的区域 — 若留在帧中则上栈,若离开则上长寿 arena。不被拒绝,不是 use-after-free。逃逸分析在每次构建上运行(--no-escape-analysis 标志关闭的是栈分配优化,而非放置的正确性)。没有 destroy()/finalize() — arena 释放就是回收机制。参见 内存安全

释放发生在离开块的每一条路径上 — 从结尾掉落、从块内 return、离开块的 break/continue(带标签或不带)。抛出异常是唯一的缺口:它越过帧展开而不释放 arena。

String 不是 arena 内存。 只有 new — 对象、数组、struct — 路由到活动 arena。一个 String 的 body(每个 +substringvalueOfStringBuilder.toString())单独分配且永不回收,无论在 arena 块内还是块外。一个 arena 块不约束构建字符串的代码的开销;在热路径上复用一个 StringBuilder 或在 byte[] 中操作。

local — 栈分配(开发者特权)

local 声明一个栈分配的对象或数组(下放为 alloca):

local Point p = new Point(1, 2);   // 在栈上,函数返回时释放

约束:不能用于原始类型(local int x 是错误),必须有初始化器。编译器不对 local 做逃逸检查 — 一个逃逸出其作用域的 local 引用是未定义行为,就像 C 的栈指针。需要经过检查的安全形式时用 arena 块。

string / String 是 UTF-8,按字节索引

单一类型(stringString 的关键字别名)。刻意与 Java 不同:

Java StringSuperJ String
编码UTF-16构造上的 UTF-8
length()UTF-16 码元数UTF-8 编码的字节数
charAt(i)一个 16 位 char码点索引;用 charAt/码点访问返回 int
后端存储char[]byte[] 为后端、长度前缀、NUL 结尾,便于零拷贝 C 交接
==引用同一性引用同一性(与 Java 相同 — 用 .equals() 比较内容)

内嵌的 NUL 是一个普通字节"ab\0cd".length() == 5,所有 String 方法都遵循存储的长度,而非第一个 NUL。NUL 唯一咬人的地方:交给 printf("%s")/原生代码的原始 C 字符串视图会在第一个 NUL 处停止。真正的二进制数据应放在 byte[],而不是 String

数组携带运行时 elem_size,且不是 Object

数组没有对象头 — 一个小的 length/elem_size 前缀然后是元素。后果:

泛型是擦除式的,原始类型不能作为类型参数

T 擦除为 ObjectT extends Foo 擦除为 Foo。在擦除签名不同处生成桥接方法。没有自动装箱,所以 List<int> 是编译错误 — 使用原始类型特化集合(IntArrayListInt2IntMap、…)或 int[]

异常全部为非受检

try/catch/finally/throw/multi-catch/try-with-resources 都和 Java 一样工作。声明上的 throws 被接受但不强制 — 它只是文档。每个异常都是非受检的;编译器从不要求你捕获或声明一个。

instanceof 模式匹配与流作用域

if (obj instanceof String s) {
    // s 在此作用域内且类型为 String,仅在此处
    return s.length();
}
// s 在此处不在作用域内

流作用域:绑定在 if 的 then 分支、while 循环体中,以及在守卫 if (!(obj instanceof T t)) return; 之后有效。绑定是 final — 重新赋值是编译错误。数组被排除作为 instanceof/转型目标(无对象头)。

明确赋值被强制

局部变量在赋值前读取是编译错误,与 Java 相同 — 但 SuperJ 严格执行。不会意外读到垃圾值。


4. SuperJ 中新增的(Java 没有)

arena 块 — 作用域内存

arena temp {
    // new 从 temp 分配
}   // temp 在这里释放 — O(1),无扫描,无停顿

词法的,不是动态的。编译期逃逸检查让悬空引用成为编译错误。见上文 §3 与 内存安全

local — 栈作用域分配

见 §3。开发者特权,逃逸即 UB — 需要检查形式时用 arena

宽整数:i128i256i512

一等公民有符号原语,可在 int/long 能用的任何地方使用:

i128 mask  = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL;
i256 big   = mask * mask;
i512 huge  = ...;
long  to   = (long) mask;        // 收窄转型

复数:cdoublecfloat

一等公民复数原语 — 两个浮点值(实部 + 虚部)打包为一个原语类型:

cdouble z  = ComplexMath.fromPair(3.0, 4.0);   // 3 + 4i
cdouble j  = 0.0 + 1.0i;                        // 虚数字面量 → 1i
cdouble w  = z * z;                              // (3+4i)² = -7+24i
double  r  = ComplexMath.real(z);               // 3.0
double  im = ComplexMath.imag(z);               // 4.0
double  a  = ComplexMath.abs(z);                 // 5.0
cdouble e  = ComplexMath.exp(j);                // e^i = cos(1)+i·sin(1)

字面量语法: i 后缀表示虚数单位 — 3.0i 是一个实部=0、虚部=3.0 的 cdouble2.5fi 是一个实部=0、虚部=2.5 的 cfloat。组合实部与虚部字面量可构造一个复数值:ComplexMath.fromPair(3.0, 4.0) 产生 3 + 4i

算术语义:

数组: cdouble[]cfloat[] 是普通数组 — 每个元素是一个连续的实部+虚部对。热数值循环可用 --no-bounds-check

ComplexMath SDK 类sj.lang.ComplexMath):静态方法对应 java.lang.Math,基于 C99 <complex.h>

方法 (cdouble)cfloat 变体说明
abs(cdouble) → doubleabsF模 `\z\`
arg(cdouble) → doubleargF辐角(相位角)
conj(cdouble) → cdoubleconjF复共轭
exp(cdouble) → cdoubleexpFe^z
log(cdouble) → cdoublelogF自然对数
sqrt(cdouble) → cdoublesqrtF平方根
sin/cos/tansinF/cosF/tanF三角
sinh/cosh/tanhsinhF/coshF/tanhF双曲
pow(cdouble, cdouble)powFbase^exp
real(cdouble) → doublerealF实部
imag(cdouble) → doubleimagF虚部
norm(cdouble) → doublenormF`z²`(平方和)
fromPair(double, double) → cdoublefromPairF由实部+虚部构造

浮点确定性注意: 复数 */ 涉及多次浮点运算(可能应用融合乘加),因此结果是架构相关的 — 不要跨架构断言逐位相同的复数浮点输出。这与实数浮点注意事项一致:跨平台比较复数结果时使用容差。

struct — 固定布局线上类型

一个 struct 是一个具有已知、紧凑字节布局的值类型 — 无对象头、无同一性、无继承、无接口。为线上格式与零拷贝协议代码设计。深入讲解见 struct 指南

struct Header {
    int    magic;
    long   timestamp;
    byte[16] uuid;          // 定长数组字段
    string payload;         // 变长:尾部数据区中的 UTF-8 文本
}

合成的访问器 — 写入与读取 — 在一次轻量往返中:

struct Order {
    long   id;          // 固定原语
    int    qty;
    byte   side;        // 0 = buy, 1 = sell
    string symbol;      // 变长 UTF-8 文本
    bytes  memo;        // 变长原始字节
}

// 写入 — 把一个轻量绑定到缓冲区并填充字段(无逐字段分配):
byte[] buf = new byte[256];
Order w = Order.view(buf, 0);
w.id = 42;
w.qty = 100;
w.side = 1;
w.symbol = "GOOG";                // string 字段  <- 一个 String
w.memo   = new byte[]{7, 8, 9};   // bytes  字段  <- 一个 byte[]
int n = w.totalSize();            // Order.SIZE + 4 ("GOOG") + 3 (memo);要发送的字节

// 读取 — 把一个新视图绑定到这些字节;每个字段读回为其声明类型:
Order r = Order.view(buf, 0);
long   id   = r.id;               // 原语  -> 其值  (42)
int    qty  = r.qty;              //               (100)
String sym  = r.symbol;           // string 字段 -> 一个 String  ("GOOG")
byte[] memo = r.memo;             // bytes  字段 -> 一个 byte[]   ({7,8,9})
// String s = new String(r.symbol);   // 也可用:一个独立副本

你按声明类型赋值每个字段,并以同样方式读回 — 一个 string 字段两侧都是 String,一个 bytes 字段两侧都是 byte[]。变长字段(symbolmemo)按声明顺序写入;reset() 回卷以重新填充同一缓冲区。

矩形数组:int[,]int[,,]

连续、按步长索引,与锯齿 int[][]不同的类型

int[,] m = new int[3, 4];     // 单次分配,行主序
m[1, 2] = 7;
int total = m.length;         // 12(各维度之积)

一等公民 SIMD 向量

通过内建 Simd 类访问 — 无新语法、无新关键字。小型定长数组是容器;Simd 方法把它们当作向量寄存器操作:

float[4] a = ..., b = ..., c = new float[4];
Simd.addFloat4(a, 0, b, 0, c, 0);   // c = a + b,4 个通道同时

向量族(元素类型 + 通道数,编码在方法名后缀中):

宽度ISA
128 位SSE2Byte16Short8Int4Long2Float4Double2
256 位AVX2Byte32Short16Int8Long4Float8Double4

i128boolean 不是 SIMD 元素类型。命名:Simd.operation<Family>(src, srcOff, …, dst, dstOff)。操作:算术、位、比较(产生掩码通道 0/-1)、blend、转换(加宽/收窄)、归约(sum/min/max/any/all)、数学(sqrt/floor/fma)、gather/scatter、点积、前缀和、加载/存储(对齐 + 非对齐)。完整操作列表见 SIMD 参考(随 SDK 源码发布)。--simd=sse2|avx2|none 选择目标 ISA(sse2 默认;avx2 启用 256 位族)。

native 方法 — 直达 C ABI

public class Crypto {
    public native static long hash(byte[] data, int len);
}

系统 SDK(一览)

开箱即用;每个包都在 sj.* 下:

内容
sj.langStringStringBuilderMathComplexMathIntegerLongShortByte
sj.utilArrayListIntArrayListLongArrayListHashMapInt2IntMapInt2ObjMapHashSetArraysHashRandom
sj.ioFileFileReaderFileWriterCloseable
sj.http增量式 HTTP/1.1 服务器、ContentTypeCookie、TLS 1.3
sj.json手写增量式 JSON 解析器
sj.seda事件驱动框架(App → Sequencer → 事件队列)
sj.cryptoSHA256(ARM NEON)、Secp256k1、EthereumAddress、EIP-712、TLS 引擎
sj.netNioAdapter 事件循环(TCP/UDP/Unix、epoll/kqueue)、UnixGateway
sj.testAsserts、单元测试运行器

superj doc --listsuperj doc <class-fqn> 发现 API。


5. 速查语法表

扫一眼找到你需要的构造。"Java 形式"是你在 Java 中会写的;"SuperJ 形式"是你在这里写的。

构造Java 形式SuperJ 形式备注
Hello worldpublic class H { public static void main(String[] a){ System.out.println("hi"); } }相同完全一致
字符串类型StringstringStringstring 是关键字别名;单一类型
字符串长度s.length()(UTF-16 码元)s.length()字节)/ s.charCount()(码点)UTF-8
声明泛型列表List<Integer> xsArrayList<Integer> — 或 IntArrayListint 不能作类型参数;无装箱
Lambda() -> doX()Thing::doX仅方法引用;指向 SAM 接口
函数式目标Runnable r = () -> …Runnable r = MyClass::runSAM 接口,无捕获
内部类class Outer { class Inner {} }class Outer { static class Inner {} }仅静态嵌套
带捕获的匿名类new Foo() { void m(){ use(local); } }new Foo() { void m(){ /* 不能用 local */ } }匿名类不捕获
线程new Thread(r).start()跑一个进程;或一个 SEDA app无线程
synchronized (obj) { … }无;单线程
内存清理obj = null;(给 GC 的提示)什么都不用;或 arena 块释放无 GC;arena 在作用域退出时释放
作用域临时内存(无对应)arena temp { … }新增 — 块退出时 O(1) 释放
栈对象(无对应)local Point p = new Point(1,2);新增 — 逃逸即 UB
128 位整数BigIntegeri128 x = …;一等公民原语
256 位整数BigIntegeri256 x = …;一等公民原语
512 位整数BigIntegeri512 x = …;新增;不能跨 native
复数 (double)(无对应)cdouble z = ComplexMath.fromPair(3.0, 4.0);新增;两个 double 打包为一个原语
复数 (float)(无对应)cfloat w = ComplexMath.fromPairF(2.0f, 3.0f);新增;两个 float
虚数字面量(无对应)cdouble j = 1.0i;新增;i 后缀 = 虚数单位
线上格式记录(无对应)struct Header { int magic; … }新增;Header.view(buf, off) 轻量视图
二维密集数组int[][] gridint[,] grid新增;连续、按步长索引
三维密集数组int[][][] cubeint[,,] cube新增
SIMD 加 4 个 float(无直接对应)Simd.addFloat4(a, 0, b, 0, c, 0)新增;float[4] 是容器
调用 CJNI 样板public native static long hash(byte[] d, int n);新增;修饰后的 sj_… 符号
受检异常throws IOExceptionthrows IOException(被接受,不强制全部非受检
try-with-resourcestry (var r = …) { … }相同资源需有 void close()
Multi-catch`catch (AB e)`相同
带标签 break/continueouter: for… break outer;相同Java 语义;展开 try-finally
instanceof 模式if (x instanceof T t)相同流作用域;排除数组
测试方法JUnit @Test@Test static void name() { … } + // UNIT 标记内建运行器
跳过测试@Ignore(JUnit)@Test @Ignore static void name() { … }内建
文件扩展名.java.sj
构建javac / mvn / gradlesuperj build / superj run构建系统
运行java -cp … Maintarget/<name>原生二进制

6. 保留关键字

abstract   boolean    break      byte       case       catch      char
class      const      continue   cdouble   cfloat     default    do
double     else       enum       extends    final      finally    float
for        goto       if         i128       i256       i512       implements
import     int        interface  instanceof local      long       native
new        null       package    private    protected  public     return
short      static     string     struct     super      switch     synchronized
this       throw      throws     transient  try        void       volatile
while      assert     strictfp

相比 Java 新增:arena(作用域内存)、local(栈分配)、i128/i256/i512(宽整数)、cdouble/cfloat(复数)、stringString 的别名)、struct(线上格式类型)。

保留但未使用(继承自 Java 关键字集合,未实现):constgotoassertstrictfptransientsynchronizedvolatile。它们被保留以防止你用作标识符;它们在 Java 中对应的特性已被移除(§2)或未实现。

SuperJ — manual · generated from language-reference.md at pack time · Powered by superJ — this site is served by superj_web 中文|EN