选自 justinblank

机器之心编译

参与:李志伟、张倩

在 JVM 中,一个 Java 方法,最多能定义多少参数呢?这是一个很无聊的问题,即使能定义一万个,十万个,谁又会真的去这么做呢。但是作为一个 coder,最重要的不就是好奇心吗,没有好奇心,和一条咸鱼又有什么区别呢?本文作者就是这样一位充满好奇心的 coder。

我最近给我的 QuickTheories 分支添加了一个接口:

@FunctionalInterfacepublic interface QuadFunction {    E apply(A a, B b, C c, D d);}

让我好奇的是这个方法能有多少个类型参数。到目前为止,我敢说,Java 语言规范并没有谈及这个问题。

对于实现定义的限制可能是什么,我有两个猜测:

  1. 编译器会设置一个可预测的限制,如 255 或 65535。

  2. 编译器的紧急行为会由于实现细节(堆栈溢出或同样不可预测/不相关的东西)而设置意外的限制。

我不想在源代码上测试我那点可怜的 C++技巧,所以我决定只测试编译器做了什么。我写了一个 Python 脚本,它使用二进制搜索找到最少的致错类型参数。完整的脚本放在 Github repo (https://github.com/hyperpape/java-max-type-params) 中。

脚本地址:https://github.com/hyperpape/java-max-type-params

生成方法很简单。幸运的是,我们不必使用任何类型参数,只需以的形式发出它们:

def write_type_plain(count):    with open('Test.java', 'w') as f:        f.write("public class Test {\n")        f.write("public )for i in range(count):if (i > 0):                f.write(", ")            f.write("A" + str(i + 1))        f.write("> void testMethod() {}")        f.write("}")

运行二进制搜索可以得到以下输出:

>>> error: UTF8 representation for string " is too long for the constant pool>>> largest type: 2776

这个错误有点模糊,但事后看来是可以预见的。编译器生成的类文件包含许多字符串,包括类中每个方法的方法签名。这些字符串存储在常量池中,常量池中的条目最大为 65535 字节,这是由 JVM 规范规定的限制。

所以,我之前的猜测都不完全正确。类型参数的最大数目是一个突现特征(emergent property),而不是一个明确的决定。不过,并不是编译器本身的实现导致了错误。

相反,JVM 的类文件格式限制了可以在类文件中表示的类型参数的数量。这是真的,尽管 JVM 对泛型一无所知。这也意味着类型参数的最大数目完全取决于如何编写方法。

我尝试了一种新的编码类型参数的方法(先前链接文件中的 write_Type_Compact),使用完整的合法 ASCII 字符(A-Z、a-z、$和_)。该实现有点过于复杂,因为可以使用字符 0~9,但不能是标识符的初始字符,因为 Java 关键字不能作为类型参数出现。我只是用等长的 UTF-8 字符替换了短单词「if」和「do」。更紧凑的编码将参数数量从 2776 增加到 3123。

不方便的是,_A 是一种合法的 Java 标识符,但 _ 不是。谢天谢地,我的编码在不使用初始_情况下就生成了 3392 个 2 字节类型参数,因此我觉得没有必要进行簿记以发出初始字符_。

再来一个小技巧

解压类文件显示,65536 个字符的大部分不是我生成的类型参数,而是子字符串 Ljava/lang/object 的重复实例。因为没有提供关于类型参数的信息,所以类文件显示它们扩展了对象,并在方法签名中对其进行编码。我修改了生成器来解决这个问题。

循环的关键部分是:

s = type_var(i)f.write(s)if (s != 'A'):    f.write(" extends A")

在类型参数中,除了一个实例 java/Lang/Object 之外的所有实例都被替换为 A。在进行了这个更改之后,编译了一个具有 9851 个类型参数的方法。

由于参数的数量增加了很多,所以我使用的代码肯定需要调整。使用非 ASCII Unicode 标识符可能是完全高效的必要条件,但简单地指出这是可以做到的我就很满意了。

这些都不重要

很难想象有人会达到这个极限。代码生成有时会达到语言或编译器的限制,但即使生成的代码似乎也不太可能使用成百上千的类型参数。

尽管如此,如果我是规则制定者,我会考虑明确禁止任何类或方法具有 255 个以上的类型参数。明确的限制似乎更好,即使它只影响百万分之一的程序。

原文链接:http://justinblank.com/experiments/howmanytypeparameterscanajavamethodhave.html

本文为机器之心编译,转载请联系本公众号获得授权

✄------------------------------------------------

加入机器之心(全职记者 / 实习生):hr@jiqizhixin.com

投稿或寻求报道:content@jiqizhixin.c

java方法参数类型不确定_一个Java方法能有多少个参数类型?这个好奇coder做了个实验...相关推荐

  1. 420一个像素多少个字节_一个Java方法能有多少个参数类型?这个好奇coder做了个实验...

    在 JVM 中,一个 Java 方法,最多能定义多少参数呢?这是一个很无聊的问题,即使能定义一万个,十万个,谁又会真的去这么做呢.但是作为一个 coder,最重要的不就是好奇心吗,没有好奇心,和一条咸 ...

  2. 一个Java方法能有多少个参数类型?这个好奇coder做了个实验

    在 JVM 中,一个 Java 方法,最多能定义多少参数呢?这是一个很无聊的问题,即使能定义一万个,十万个,谁又会真的去这么做呢.但是作为一个 coder,最重要的不就是好奇心吗,没有好奇心,和一条咸 ...

  3. java值传递和引用传递_辨析Java方法参数中的值传递和引用传递

    小方法大门道 小瓜瓜作为一个Java初学者,今天跟我说她想通过一个Java方法,将外部变量通过参数传递到方法中去,进行逻辑处理,方法执行完毕之后,再对修改过的变量进行判断处理,代码如下所示. publ ...

  4. Java main方法_解释Java中的main方法,及其作用_一个java文件中可包含多个main方法

    public static void main(String[] args) {} 或者 public static void main(String args[]) {} main方法是我们学习Ja ...

  5. 判断类型是否继承_【Java学习 | Javase】继承与多态

    整理自:老师课件.<Java核心技术> 继承与多态 继承 概念 父类/超类 所有子集的公共域和公共方法的集合 子类 父类的特殊化,是对公共域和方法在功能.内涵方面的拓展和延伸 object ...

  6. 一个java类可以有_一个.java文件中可以有几个同级类?

    1.在一个.java文件中可以有多个同级类(和public一样的位置,注意不是内部类).其修饰符只可以public/abstract/final/和无修饰符,不能是其他的protected/priva ...

  7. java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器

    java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器 下载地址:http://yunpan.cn/QXhEcGNYLgwTD 运行方式:java -jar Encryp ...

  8. java定义一个空数组_一个 Java 方法,最多能定义多少参数?

    点击上方"JAVA",星标公众号重磅干货,第一时间送达 文链接:http://justinblank.com/experiments/howmanytypeparametersca ...

  9. java类名可以是数字吗_在 Java 中,一个类可同时定义许多同名的方法,这些方法的形式参数的个数、类型或顺序各不相同,传回的值也可以不相同。这种面向对象程序特性称为( )。_学小易找答案...

    [简答题]Java 支持多继承吗 ? [单选题]以下关于继承的叙述正确的是( ). [单选题]在 Java 中,一个类可同时定义许多同名的方法,这些方法的形式参数的个数.类型或顺序各不相同,传回的值也 ...

最新文章

  1. ffmpeg+ffserver搭建流媒体服务器
  2. Day 08 周六下午的活动
  3. Codeforces 1206
  4. 007_html头部元素
  5. MFC 定时器用法 SetTimer、KillTimer
  6. html5的canvas元素使用,HTML5canvas元素概念及使用方法介绍
  7. (轉貼) C Standard Library (初級) (C/C++)
  8. 每天一个实用小技巧!巧妙利用Mac标记,分类同类文件
  9. 2018 Multi-University Training Contest 7 - GuGuFishtion
  10. android逆向学习路线(适合新手)
  11. protues仿真8086常见问题
  12. qt opengl 天空盒
  13. 吉他入门教程之吉他音阶训练——认识音阶
  14. 5.2 Photoshop复制图层的几种方式 [原创Ps教程]
  15. 东方联盟郭盛华:物联网安全是供应链问题
  16. 僵尸网络(botnet) DDoS
  17. 如何升级win10.
  18. 使用RTMP协议实现视频桌面共享功能
  19. 开发自己的DJI四旋翼无人机(A3飞控Onboard SDK和Mobile SDK介绍)
  20. 百度地图api之固定标记点(标记点自己设置样式)

热门文章

  1. Kogito人机规则-第1部分:进一步解决流口水
  2. java jax-rs_在Java EE 7和WildFly中使用Bean验证来验证JAX-RS资源数据
  3. 变异测试 java_编码的喜悦……以及Java中的变异测试
  4. Java开发趋势:2019年展望
  5. gradle 命令行_Gradle命令行便利
  6. 用于从文件读取/写入字符串的新JDK 11文件方法
  7. 高级java开发_适用于高级Java开发人员的十大书籍
  8. 在Java中进行输入验证时用错误通知替换异常
  9. 适用于Java开发人员的Elasticsearch:Java的Elasticsearch
  10. 在JPA和JDBC中使用存储过程。 嗯,只要使用jOOQ