点击上方“JAVA”,星标公众号重磅干货,第一时间送达

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

在 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 ">>> 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 个以上的类型参数。明确的限制似乎更好,即使它只影响百万分之一的程序。

--END--

▐ 推荐

【大数据】教程 完整版

【JAVA】从零基础到精通完整版视频 附源码+工具+笔记文档 IDEA版

【Web前端】WEB前端全栈工程师开发 附完整视频+源码+工具

【软件测试】从零基础到软件测试工程师 附完整视频+工具+面试简历

IntelliJ IDEA 2020.2 EAP 5 发布:完美支持Java 15

面试:说说Java中的 volatile 关键词?

公众号ID|javabaiwen

小编微信|619531440

每天分享技术干货

视频 | 电子书 | 面试题 | 开发经验

java定义一个空数组_一个 Java 方法,最多能定义多少参数?相关推荐

  1. python定义一个空数组_在NumPy中如何创建一个空的数组/矩阵?

    如何以我通常使用列表(List)的方式使用Numpy数组或矩阵? 我想创建一个空的数组(或矩阵),然后每次添加一列(或行)到这个数组(或矩阵). 目前能想到的方法是: mat = None for c ...

  2. java list 去空字符串_【JAVA基础】list和字符串判空

    前言: 我们在项目中经常需要对获取的list集合或String类型变量判空,看前辈的代码,不同的人判空的方法不一样,那么,Java代码中,对list集合和String类型变量到底该如何判空呢? 一.J ...

  3. java字符串拆分成数组_用Java实现JVM第八章《数组和字符串》

    小傅哥 | https://bugstack.cn 沉淀.分享.成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获.目前已完成的专题有:Netty4.x实战专题案例.用J ...

  4. java合并两个数组_「JAVA」两个数组的交集—力扣每日一题(一)

    示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] ...

  5. java整型转换为数组_基于java中byte数组与int类型的转换(两种方法)

    java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中,发送.者接收的数据都是 byte数组,但是int类型是4个byte组成的,如何把一个整形 ...

  6. java 获取spring对象数组_解析Java中如何获取Spring中配置的bean

    解析Java中如何获取Spring中配置的bean Java中如何获取Spring中配置的bean?下面是由百分网小编为大家整理的解析Java中如何获取Spring中配置的bean,喜欢的可以收藏一下 ...

  7. java主类调用数组_用java编写在主函数中调用数组

    importjava.util.Scanner;publicclassja{publicstaticvoidmain(Stringargs[]){Scannerscanner=newScanner(S ...

  8. 结构体后面定义一个空数组的含义

    最近在写C代码,经常看到Linux 的头文件中有的结构体后面会定义一个空数组,不知道其为何作用?经过高人指点终于明白其要点! struct inotify_event {    __s32 wd;   ...

  9. python定义一个空数组_python如何创建空数组?

    Python创建空数组的三种方式: 1.numpy指定形状为0 实际上,empty生成的数组当然可以为空,只要我们指定了相应的形状.例如,如果我们传入数组的形状参数为(0,3),则可以生成目标空数组: ...

最新文章

  1. R语言使用geompointdensity包的geom_pointdensity函数将散点图和密度图结合起来、使用viridis包的scale_color_virdis函数为密度数据添加调色板色彩渐变
  2. 《互联网运营智慧》之自序(新)
  3. 学习笔记 Keras:一些基本概念
  4. org.springframework.beans.factory.BeanDefinitionStoreExcept
  5. c#编程指南(十二) 平台调用P-INVOKE完全掌握, 结构体边界对齐和内存布局
  6. ExtJs TreePanel使用TreeLoader在IE下无法正常加载显示的解决方法
  7. 晶闸管调压电路的matlab仿真,基于SIMULINK晶闸管调压电路仿真及分析.doc
  8. GPS里集成的指南针一般叫做外置罗盘是1#,飞控里面的指南针叫内置罗盘是2#
  9. c语言题 设圆的半径,C语言初学者:编程序:设圆半径r圆柱高h,求圆周长面积圆柱体积圆球表面积...
  10. adb 连接某个wifi_使用adb命令连接WiFi进行无线调试
  11. LiveZilla 3.2.0.2的汉化包
  12. [nlp] LLS减少学习捷径:分析和缓解伪特征标签相关性
  13. 已经过去2周了,你感觉怎么样?
  14. github windows系统监控_你需要的:Windows | 精品软件集
  15. 【良心教程】保姆级Python爬虫入门教程(一)——爬虫之初见
  16. TF-IDF算法及实现
  17. mysql返回数据只要年月日_MySQL支持按年月日查询
  18. 《小强升职记》读书笔记(上)
  19. excel自动排班有假期_在Excel中计划您的假期晚餐
  20. Three Friends

热门文章

  1. java实现linux中gzip压缩解压缩算法:byte[]字节数组,文件,字符串,数据流的压缩解压缩
  2. python123.io简单编程题合集
  3. python-django rest framework框架之序列化
  4. Python3 爬虫之 Scrapy 核心功能实现(二)
  5. 扩展 delphi 泛型 以实现类似lambda功能 , C#中的any count first last 等扩展方法
  6. Oracle学习笔记之五sp1,PL/SQL之BULK COLLECT
  7. 不能不说的C#特性-表达式树
  8. [转载] 利用python制作简单计算器
  9. [转载] Python算法
  10. Solidity语言基础 和 Etherum ERC20合约基础