位于上海,服务全国!

位于上海,服务全国!

在NetBeans 9.0中使用Java 9的JShell,第3部分

作者:admin 分类: 时间:2019-03-06 22:14:16 点击量:2221


JShell是一个命令行工具,可以在Shell环境中运行代码片段,而无需编译和运行完整的应用程序。JShell是Java 9中的一个新功能。JShell可以用于在开发应用程序时测试和调试代码片段。JShell输入应该采用完整的代码片段的形式。我们已经发布过两篇介绍JShell的文章:“在NetBeans 9.0中使用Java 9的JShell,第1部分”和“在NetBeans 9.0中使用Java 9的JShell,第2部分”,其中我们讨论了运行导入语句、声明和使用变量、比较字符串和运行语句。在这篇接续性文章中,我们将运行Java方法的代码段。本文分以下几个部分:


设置环境
使用方法
修改方法定义
方法重载
前向引用一个方法
列举法
不允许修改器的高级方法声明
结论


设置环境
下载并安装NetBeans,正如以前的文章中所讨论的。在Java平台shell中,通过选择工具>打开来启动JShell,如图1所示。


 
图1:工具>开放Java平台壳
使用方法
在JShell中声明一种方法,与在Java应用程序基本相同,但有些细微差别,其会在本节中被讨论。例如,声明一个方法triple(int),该方法接受int参数并返回int值。


int triple(int i) {
   return i*3;
}
在JShell中运行代码片段,并创建一个方法。


[10]-> int triple(int i) {
   return i*3;
}
创建方法triple(int)
用int值作为参数调用方法triple。
triple(1)
参数值是原来的三倍并返回。
[11]-> triple(1)
|  $13 ==> 3
[12]->


该方法有一个返回类型和参数,但没有访问修饰符,如public、private或protected。这是因为顶级方法声明与所有顶级声明一样,都是隐式公开的。忽略顶级方法声明中的任何访问修饰符。下面的所有方法声明都与前面的方法声明等效。


[1]-> private int triple(int i){
   return 3*i;
}
|  created method triple(int)
[2]-> protected int triple(int i){
   return 3*1;
}
|  replaced method triple(int)
[3]-> public int triple(int i){
   return 3*i;
}
|  replaced method triple(int)
[4]->
JShell显示编译时错误(如果有的话)。例如,将方法的返回类型设置为String,然后显示错误消息。


[10]-> String triple(int i) {
   return i*3;
}
|  Error:
|  incompatible types: int cannot be converted to java.lang.String
|     return i*3;
|     ^-^
修改方法定义
输出的消息是“替换方法…”,但无法通过Java应用程序生成,在本节中已经列出了两次。该消息提示出该方法的定义已被修改。替换/修改方法声明和其他声明的规定是为了方便于测试。


为了在无需定义新方法的情况下修改或替换方法,就不能修改方法签名,其由方法名称和方法参数设置,且包括参数的数量及其类型和顺序。作为示例,使用返回类型void和String类型参数声明一个方法hello。


[4]-> void hello(String s){
}
创造方法hello(String)
接下来,使用返回类型String、String类型参数和返回语句声明相同的方法hello。替换前面的用于hello的方法声明。


[5]-> String hello(String s){
   return "Hello " + s;
}
|  replaced method hello(String)
[6]->


调用方法hello(String),然后调用第二个方法定义以输出“Hello John”消息。


[6]-> hello("John")
|  $5 ==> "Hello John"


[7]->
如果需要,在方法调用中串联方法参数,如下面的代码片段所示。


[7]-> hello("John"+" & "+"Johnny")
|  $22 ==> "Hello John & Johnny"
[8]->
在前面的修改方法的示例中,我们将返回类型void替换为String。不需要修改返回来替换方法。作为示例,定义方法hello如下。


[15]-> String hello(String str1, String str2){
   return str1+str2;
}
|  created method hello(String,String)
接下来,只修改return语句。hello(String,String)方法被替换。


[16]-> String hello(String str1, String str2){
   return "Hello"+str1+str2;
}


|  replaced method hello(String,String)
作为运行方法代码片段的另一个示例,使用返回类型String[]定义方法hello(String str1,String str2)。
[17]->
String[] hello(String str1, String str2){
   return new String[]{str1,str2};
}
|  created method hello(String,String)
使用两个参数调用方法以返回数组。
[18]-> hello("John","Michael")
|  $39 ==> String[2] { "John", "Michael" }
方法重载
方法可能如在Java应用程序一样被重载。声明一个方法hello(String s)。
[1]-> String hello(String s){
   return "Hello  " + s;
}
|  created method hello(String)
调用该方法以输出消息。
[2]-> hello("John")
|  $1 ==> "Hello John"
声明另一个方法hello(String,String)。
[3]-> String hello(String str1, String str2){
   return str1+str2;
}
|  created method hello(String,String)
调用该方法以输出消息。
[5]-> hello("Hello"," John")
|  $16 ==> "Hello John"
对一个方法进行前向引用
JShell支持对一个方法进行前向引用。前向引用调用尚未定义的方法。声明方法main(String),其被引用至尚未定义的方法hello(String)。方法main(String)的确被创建,但是除非定义了方法hello(String),否则无法调用它。


[1]-> String main(String str){
   return "Hello "+hello(str);
}
|创建方法main(String),但如果方法Hello(Java.Lang.Stand)没有被声明,该方法无法调用
调用方法main(String),输出一个消息,表明它不能被调用。


[2]-> main("Michael")
|试图调用无法调用的方法main(String)
|直到声明方法hello(java.lang.String)
|声明main(String)引用的方法hello(String)。
[3]-> String hello(String name){
   return name;
}
|创建方法hello(String)
随后,再次调用方法main(String)。


[4]-> main("Michael")
|  $1 ==> "Hello Michael"
如果不在顶级变量声明中添加和在方法声明中添加,则按行隐式添加“;”。但是,“;”并不隐含在方法内的语句中。作为示例,声明以下方法,然后输出一个错误。


[1]-> int average(int i,int j){
   return (i+j)/2
}
|  Error:
|  ';' expected
列出方法
通过/methods命令列出在给出的JShell会话中定义的方法。为了演示,需要定义一些方法。
[1]-> int triple(int i) {
   return i*3;
}
|  created method triple(int)
[2]-> String hello(String s){
   return "Hello" + s;
}
|  created method hello(String)
[3]-> String hello(String str1, String str2){
   return str1+str2;
}
|  created method hello(String,String)
[4]-> int average(int i,int j){
   return (i+j)/0;
}
|  created method average(int,int)
运行/methods命令,然后列出所有添加的方法。
[5]-> /methods
|    printf (String,Object...)void
|    triple (int)int
|    hello (String)String
|    hello (String,String)String
|    average (int,int)int
[5]->
顶级方法声明中不允许使用的修改器


尽管顶级方法声明中的修饰符public、private和protected可被忽略,并且方法定义是通过公共访问隐式创建的,但是某些其他修饰符不会被忽略,并且不允许在顶级方法声明中被声明。这些修饰符在顶层是不允许的,因为这些修饰符在某些上下文中有重要意义,并且不适合用于测试代码片段的JShell上下文。
当在类或接口的上下文中与方法一起使用时,静态修饰符就有意义,但不是在顶层。作为示例,运行以下包含静态参数的方法声明。
[1]-> static String hello(String name){
   return "Hello "+name;
}
|  Warning:
|  Modifier 'static' not permitted in top-level declarations,
|  ignored
|  static String hello(String name){
|    ^----^
|  created method hello(String)
静态修饰符会被忽略,仅输出一个警告,但是会创建一个方法,且可以调用该方法。
[2]-> hello("John")
|  $1 ==> "Hello John"
[3]->
类似地,无论在方法声明或任何其他声明中,修饰符final在顶层都没有意义,因为JShell被设计成动态地运行代码片段,并且在声明一个方法(或变量,或类)final将使代码片段不可修改。例如,向方法添加最后的修饰符。忽略最后一个修饰符,生成警告,并且创建方法定义时没有使用final。


[2]-> final int triple(int i){
   return 3*i;
}
|  Warning:
|  Modifier 'final' not permitted in top-level declarations,
|  ignored
|  final int triple(int i){
|    ^---^


|创建方法triple(int)
调用该方法并输出结果。
[3]-> triple(5)
|  $1 ==> 15
[4]->
无论在方法或任何其他声明中,顶层也不允许使用其他一些修饰符。尽管忽略了静态修饰符和final并创建了方法定义,但是顶级方法中的抽象和本机修饰符生成一个错误,并且不会创建方法。


[1]-> abstract String hello(String s){
   return "Hello "+s;
}
|  Error:
|  Modifier 'abstract' not permitted in top-level declarations
|  abstract String hello(String s){
|    ^------^
[1]->


[1]-> native String hello(String s){
   return "Hello "+s;
}
错误:
|顶级声明中不允许的修改符'native'
|本机String hello(String s){
|    ^----^
在顶级方法声明或任何其他声明中默认和同步的修改符不允许有,其会产生错误。


结论
在本文中,我们讨论了JShell中Java方法的运行代码片段。在随后的文章中,我们将讨论Java类、接口和数组的运行代码片段。