gpt4 book ai didi

Java方法能定义多少个参数你知道吗

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 24 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章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.

?
1
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的办法:

?
1
2
3
4
5
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源码,在生成方法的字节码时,有方法参数数量限制判断:

?
1
2
3
4
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文件加上一个新方法即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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试试:

?
1
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源码中搜索了下上面报的错误,找到了虚拟机检查参数数量的地方:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
   }
  }
  ......
}

可见虚拟机在解析class文件中的方法时,会判断参数数量args_size是否大于max_args_size,如果大于则就会报错了。max_args_size为255.

这里有一点需要注意,在计算args_size时,有判断方法是否为static方法,如果不是static方法,则会在方法原有参数数量上再加一,这是因为非static方法会添加一个默认参数到参数列表首位:方法的真正执行者,即方法所属类的实例对象.

事情到这里总算大概明白了,java static方法的参数最多只能有255个,非static方法最多只能有254个。虽然远不及我刚开始推测的65535个,但是这也完全够用了,毕竟你敢在你的项目里定义一个255个参数的方法而保证不被人打死吗.

有人可能要问,如果我定义的方法参数是变长参数呢?还有这种限制吗?这当然是没有的,因为变成参数的本质其实就是传递一个数组,你传再多的参数,编译后其实都只是一个数组而已.

一切都结束了 。

嗯,做完实验,写完文章,我总算把这件事搞明白了,女朋友早已在呼呼大睡,好像我确实很无聊,好像我确实还是一条咸鱼.

总结 。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.

原文链接:https://zhuanlan.zhihu.com/p/44086976 。

最后此篇关于Java方法能定义多少个参数你知道吗的文章就讲到这里了,如果你想了解更多关于Java方法能定义多少个参数你知道吗的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com