温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java方法可以定义多少个参数

发布时间:2021-06-11 14:49:19 来源:亿速云 阅读:243 作者:Leah 栏目:编程语言

Java方法可以定义多少个参数?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

如何定义 Java 中的方法

所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块。

一般情况下,定义一个方法的语法是:

Java方法可以定义多少个参数

其中:

1、 访问修饰符:方法允许被访问的权限范围, 可以是 public、protected、private 甚至可以省略 ,其中 public 表示该方法可以被其他任何代码调用,其他几种修饰符的使用在后面章节中会详细讲解滴

2、 返回值类型:方法返回值的类型,如果方法不返回任何值,则返回值类型指定为 void ;如果方法具有返回值,则需要指定返回值的类型,并且在方法体中使用 return 语句返回值

3、 方法名:定义的方法的名字,必须使用合法的标识符

4、 参数列表:传递给方法的参数列表,参数可以有多个,多个参数间以逗号隔开,每个参数由参数类型和参数名组成,以空格隔开

本文将详细的介绍Java方法能定义多少个参数的相关内容,下面话不多说了,来一起看看详细的介绍吧

一:为什么研究这么无聊的问题

这两天在读一本老书《Orange'S 一个操作系统的实现》,把丢了很长时间没研究的操作系统又重新拾起来了,在第三章讲解“保护模式”时,作者提到了调用门描述符中的Param Count只有5位,也就是说,最多只支持32个参数,这本来只是一个不是特别重要的细节,但是却勾起了我的思索:在JVM中,一个Java方法,最多能定义多少参数呢?我知道这是一个很无聊的问题,即使能定义一万个,十万个,谁又会真的去这么做呢。但是作为一个Coder,最重要的不就是好奇心吗,没有好奇心,和一条咸鱼又有什么区别呢?

二:实地考察

这种问题,第一步当然就是看看JVM中关于方法的定义,这里以openJDK10中的HotSpot为例。

在ConstMethod中,代表参数数量的字段为_size_of_parameters。

 u2  _size_of_parameters;  // size of the parameter block (receiver + arguments) in words

_size_of_parameters的类型为u2,在JVM中,u2为2个字节长,那么理论上来说,HotSpot支持的方法最大参数数量为2^16 - 1,即65535。

这个答案究竟是否正确呢?实践出真知!

当然我不会傻到真的去一个个定义65535个参数,那我岂不成了“数一亿粒米”的幼儿园老师了?Coder就得按照Coder的办法:

 public static void main(String[] args) {
 for (int i = 0; i < 65535; i++) {
  System.out.print("int a" + i + ",");
 }
 }

完美解放了生产力? 。

生成完参数列表,定义好方法,当我满怀信心的开始编译时,编译器给了我狠狠一刀:

Java方法可以定义多少个参数

居然不是65535?那应该是多少呢?难道是一个字节长?废话不多说,我立即来实验了下255个参数,编译通过,再试了一下256,和65535时一样报错。那么结果很明显了,Java方法最多可以定义255个参数。

我查看了下Javac源码,在生成方法的字节码时,有方法参数数量限制判断:

 if (Code.width(types.erasure(env.enclMethod.sym.type).getParameterTypes()) + extras > ClassFile.MAX_PARAMETERS) {
 log.error(tree.pos(), "limit.parameters");
 nerrs++;
 }

其中 ClassFile.MAX_PARAMETERS = 255。

事情到这里我很不甘心,HotSpot中明明是用两个字节长来定义的方法参数数量,莫非只是Javac在编译过程中做了限制?只要能成功编译出一个有256个参数的java方法,在虚拟机中一试便知,但是怎么才能绕过Javac呢?

我觉得主要有以下两种办法:

一:修改Javac源码,干掉以上参数限制这一段代码,再重新编译;

二:利用字节码修改工具,硬改字节码,加上一个拥有256个参数的方法。

第一种方法看似简单,但是其实从openJDK中提取出来的Javac项目不能直接run,需要很多配置,而且源码依赖了很多jdk中的不可见类,操作起来很麻烦。所以这里我采用了第二种方法,工具选用的是老朋友javassist。

其实javassist使用起来很简单,这里我只需要对一个已有的class文件加上一个新方法即可:

 try {
  StringBuilder sb = new StringBuilder();

  sb.append("public static void testMax(");

  for (int i = 0; i < 256; i++) {
  sb.append("int a" + i);
  if(i < 255) {
   sb.append(",");
  }
  }
  sb.append("){}");

  ClassPool cPool = new ClassPool(true);
  cPool.insertClassPath("/Users/wanginbeijing/Documents/MyProgramings/java/Mine/test/src");
  CtClass cClass = cPool.get("com.wangxiandeng.test.Test");
  CtMethod newMethod = CtNewMethod.make(sb.toString(), cClass);
  cClass.addMethod(newMethod);
  cClass.writeFile("/Users/wanginbeijing/Documents/MyProgramings/java/Mine/test/src");
 } catch (NotFoundException e) {
  e.printStackTrace();
 } catch (CannotCompileException e) {
  e.printStackTrace();
 } catch (
  IOException e) {
  e.printStackTrace();
 }

以上就通过javassist成功的给Test.class 文件加上了一个拥有256个参数的方法testMax()。现在让我们运行下Test.class试试:

 java com.wangxiandeng.test.Test

没想到这次虽然瞒过了编译器,却没有过的了虚拟机这一关,运行直接报错了:

错误: 加载主类 com.wangxiandeng.test.Test 时出现 LinkageError
        java.lang.ClassFormatError: Too many arguments in method signature in class file com/wangxiandeng/test/Test

看样子Java不仅仅在编译期会对方法参数数量做限制,在虚拟机运行期间同样会干这件事。
本着一查到底的精神,我在HotSpot源码中搜索了下上面报的错误,找到了虚拟机检查参数数量的地方:

Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
     bool is_interface,
     const ConstantPool* cp,
     AccessFlags* const promoted_flags,
     TRAPS) {
 ......
 if (_need_verify) {
  args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +verify_legal_method_signature(name, signature, CHECK_NULL);

  if (args_size > MAX_ARGS_SIZE) {
   classfile_parse_error("Too many arguments in method signature in class file %s", CHECK_NULL);
  }
 }
 ......
}

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI