[Kotlin] 为什么 kotlin 的方法名中可以有空格等特殊字符?

为什么 kotlin 的方法名中可以有空格等特殊字符?

Coding conventions 一文的 Names for test methods 部分,有如下的内容

大意是说我们在测试类中可以定义有特殊名称的方法,例如方法名可以是 ensure everything works(由于名称中有空格,所以需要把它写在一对 ````` 字符中)。 但是在 java 中,并不支持这样的语法,那么作为同样运行在 JVM 上的语言,kotlin 是如何做到这一点的呢?

我自己试了试,kotlin 中的普通类中,也可以定义名称中有特殊字符的方法(方法名要写在一对 ````` 字符中)。

结论

Java Virtual Machine Specification 中对方法名的限制比较宽松,空格(即 )等特殊字符允许出现在方法名中,所以 kotlin 并没有违反 Java Virtual Machine Specification

代码

名称中含有特殊字符的方法

我们用如下的 kotlin 代码来进行验证。(请将其保存为 C.kt

kotlin 复制代码
class C {
  fun `hello world function with a special name`(): Unit {
    println("Hello world")
  }
}

kotlinc C.kt 命令可以编译 C.kt。编译后,会生成 C.class。 我们用 javap -v -p C 来查看 C.class 的内容。 和 hello world function with a special name 方法有关的部分如下 ⬇️

text 复制代码
  public final void hello world function with a special name();
    descriptor: ()V
    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
    Code:
      stack=2, locals=1, args_size=1
         0: ldc           #13                 // String Hello world
         2: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
         5: swap
         6: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
         9: return
      LineNumberTable:
        line 3: 0
        line 4: 9
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   LC;

利用 javap 命令给出的结果,可以手动写出对应的 java 代码如下 ⬇️

java 复制代码
// 以下内容是我手动转化出来的,不保证绝对准确,仅供参考

// C 类上有注解,这里略去
public final class C {
  public C() {
    super();
  }
  
  // 注意:实际上 java 不允许在方法名里使用空格,这里只是参考 kotlin 展示一下方法名,请读者不要误会
  public final void `hello world function with a special name`() {
    System.out.println("Hello world");
  }
}

看来在 class 文件中,那个方法的名字也是 hello world function with a special name,我们写点 java 代码来验证一下。

java 代码来调用它

请将如下代码保存为 Main.java

java 复制代码
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
  public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
    C c = new C();
    for (Method method : C.class.getDeclaredMethods()) {
      System.out.println("method name is: [" + method.getName() + "]");
      method.invoke(c);
    }
  }
}

如下的两个命令可以编译 Main.java 并运行其中的 main(...) 方法。

bash 复制代码
javac -g -parameters Main.java
java Main

运行结果如下,可见我们的推测是正确的,class 文件中的文件名也是 hello world function with a special name

解释

根据我们日常写 java 的经验可知,java 代码中是不允许方法名中出现空格等特殊字符的,那么为什么 kotlin 的代码里就允许呢? 我在Java Virtual Machine Specification 的 4.2.2. Unqualified Names 找到了这样的描述

其中对方法名的限制是

  1. 方法名中至少要含有一个 Unicode 字符,且方法名中不允许 出现 . ; [ / 这4个字符
  2. 除了 <init><clinit> 这两个特殊的方法名外,方法名中不允许 出现 < > 这两个字符

这么说来,在 kotlin 中,方法名也仍旧是有限制的,比如方法名中应该不可以出现 . 这个字符。 如果我们把 C.kt 改成如下的内容,那么会发现,编译失败了

kotlin 复制代码
class C {
  fun `hello . world function with a special name`(): Unit {
    println("Hello world")
  }
}

参考资料

  1. Coding conventions 一文的 Names for test methods 部分
  2. Java Virtual Machine Specification 的 4.2.2. Unqualified Names
相关推荐
c++之路19 分钟前
C++20概述
java·开发语言·c++20
Championship.23.2423 分钟前
Linux Top 命令族深度解析与实战指南
java·linux·服务器·top·linux调试
橘子海全栈攻城狮38 分钟前
【最新源码】养老院系统管理A013
java·spring boot·后端·web安全·微信小程序
逻辑驱动的ken44 分钟前
Java高频面试考点18
java·开发语言·数据库·算法·面试·职场和发展·哈希算法
冷雨夜中漫步1 小时前
Claude Code源码分析——Claude Code Agent Loop 详细设计文档
java·开发语言·人工智能·ai
直奔標竿1 小时前
Java开发者AI转型第二十六课!Spring AI 个人知识库实战(五)——联网搜索增强实战
java·开发语言·人工智能·spring boot·后端·spring
one_love_zfl2 小时前
java面试-微服务组件篇
java·微服务·面试
一只大袋鼠2 小时前
Java进阶:CGLIB动态代理解析
java·开发语言
环流_2 小时前
HTTP 协议的基本格式
java·网络协议·http
爱滑雪的码农2 小时前
Java基础十三:Java中的继承、重写(Override)与重载(Overload)详解
java·开发语言