用JShell开始学习Java – 一窥Java的世界

让我们在JShell上开始学习Java吧。

为了什么而做

没有编程经验的人能够大致理解Java编程中涉及的各种概念。

基于这篇文章的内容,已经出版了“成为专业Java开发者”的书籍。

环境设置

首先从环境设置开始。
您可以从以下链接下载JDK。
http://jdk.java.net/18/

我认为对于不熟悉命令行的人来说,使用Adoptium提供的带有安装程序的软件包会更好。也可以选择17LTS版本。
https://adoptium.net/
对于Mac和Linux用户来说,可以下载tar.gz文件来

$ tar xf openjdk-18_mac-x64_bin.tar.gz

我认为这个也可以。在Windows上,您可以下载ZIP文件并将其解压到适当的文件夹中。

启动JShell

现在让我们尝试启动JShell。
使用Windows的朋友,请打开”命令提示符”,而使用Mac或Linux的朋友,请打开”终端”。

$ jshell

如果它启动了就很幸运

顺便说一句,$ jshell 是指在命令行中输入 jshell 然后按下[enter]键的格式。

如果不能启动,对于Windows系统,请尝试启动”\Program files\Eclipse Adoptium\jdk-18-hotspot\bin\jshell”。在输入”\Prog”后按下 [tab] 键会自动补全。
※ 对于Windows系统,请使用反斜杠\输入为¥。
对于Mac系统,请尝试在/Library/Java/jdk-18/Contents/Home/bin/jshell附近启动。

image.png
image.png

当你在JShell中输入任何内容并按下[Enter]键,JShell会将该输入解释为Java代码并执行。这次输入的只是一个简单的计算,但它仍然是Java程序的一部分。
因此,我们的第一个Java程序变成了12 + 23。太棒了!

以后,将以以下方式表示对jshell的输入和结果。

jshell> 12 + 23
$1 ==> 35

请在JShell中输入12+23并按下[enter]键,这样就会显示35。暂时不必考虑$1 == > 部分。

处理值

运算

刚才进行了加法运算。那么接下来试试减法吧?我来试一下4减3。

jshell> 4 - 3
$2 ==> 1

在数学中,我们使用*来表示乘法,/来表示除法。此外,我们可以用%来计算除法的余数。

jshell> 8 * 2
$3 ==> 16

jshell> 8 / 2
$4 ==> 4

jshell> 7 % 5
$5 ==> 2

3+4*2是怎么样的呢?

jshell> 3 + 4 * 2
$6 ==> 11

对不起,我只能以英文回答您的问题。请注意,以下是对句子的一种翻译,可能会有诸多表达方式。中文翻译如下:

嗯,乘法先计算了。如果用括号括起来3+4,就会先计算加法。

jshell> (3 + 4) * 2
$7 ==> 14

各种各样的类型 (kè gè de

顺便问一下,关于22/7的事情会如何发展呢?

jshell> 22 / 7
$8 ==> 3

当进行计算时,被视为一个整数。若想要小数点后的结果,也就是希望以实数的形式进行计算,可以使用22.0/7。

jshell> 22.0 / 7
$9 ==> 3.142857142857143

在Java中,如果给数字加上小数点,它就会被视为实数。另外,如果运算的任一项是实数,计算也会以实数进行。因此,在Java中,整数和实数是有区别的,计算方式也不同。

文本字符串和方法 hé

迄今為止,我們一直在處理數字。在程式中,我們也經常處理連續的字符,例如單詞、句子等等。在程式的世界中,這種連續的字符被稱為字符串。在Java中,我們使用雙引號將字符串括起來表示。

jshell> "aaa"
$10 ==> "aaa"

方法

对于字符串,我们会想要执行各种操作。例如,让我们将字符串转换为大写字母。输入”test”.toUpperCase()进行尝试。输入到 “toU” 然后按下 [Tab] 键,应该会自动补全。这种功能称为 “自动补全”。

jshell> "test".toUpperCase()
$12 ==> "TEST"
image.png
メソッド用途length()文字列の長さを取得repeat(n)文字列をn回繰り返すreplace(old, new)文字列中のoldをnewに置き換えるcharAt(index)index番目の文字を取り出すsubstring(begin, end)文字列のbegin番目からend番目の手前までを抜き出すtoUpperCase()文字列を大文字にするtoLowerCase()文字列を小文字にする

让我们尝试使用其他方法。请执行”test”.repeat(3)的代码。

jshell> "test".repeat(3)
$13 ==> "testtesttest"

测试重复了3次的字符串被显示出来了。repeat方法是一个指定字符串重复次数的方法。就像这样,有时候我们需要向方法提供一些特定的值。这些特定的值称为”参数(引数)”。

在charAt方法中,您可以提取指定位置的字符。

jshell> "test".charAt(2)
$13 ==> 's'

在这里,需要注意的是第一个字符是0号。在程序中,大多数情况下,0表示第一个元素,1表示第二个元素。

再来一个例子,我们试着使用replace方法。让我们执行”test”.replace(“st”,””)。

jshell> "test".replace("st","")
$14 ==> "te"

replace(替换)方法是一个用于替换字符串的方法,它接受替换前的字符串和替换后的字符串作为参数。当有两个或更多参数时,我们可以使用逗号来分隔参数。””代表空字符串。通过将”st”替换为””,我们将从字符串中省略了”st”。

您还可以将方法调用连接起来。

jshell> "test".repeat(3).replace("st","")
$15 ==> "tetete"

“test”重复3次成为”testtesttest”,并且省略了”st”变成了”tetete”。

练习:使用repeat方法创建一个重复四次的字符串”hi”。
练习:使用replace方法将”grape”的字母p替换为d。
练习:使用toLowerCase方法将”HELLO”转换为小写。
练习:使用substring方法从”minute”中提取第二个字符开始的三个字符,创建一个新的字符串。

在中文中,我们使用“+”运算符来连接字符串。

jshell> "te" + "st"
$11 ==> "test"

对于减法,会怎样呢?如果用”test”减去”st”得到”te”,那么就很方便了。

jshell> "test" - "st"
|  エラー:
|  二項演算子'-'のオペランド型が不正です
|    最初の型: java.lang.String
|    2番目の型: java.lang.String
|  "test" - "st"
|  ^-----------^

发生了错误。这里所说的 “操作数” 是指运算符的项。它指出 – 运算符不能用于字符串。希望您能正确阅读这样的错误信息,但目前对于 – 运算符不能用于字符串的认识就够了。对于字符串,只能使用 + 运算符作为运算符。

操作JShell

当你按上方向键时,先前输入的内容将会出现。这对于想要再次执行先前输入的内容的情况非常有用。

要结束JShell,可以使用/exit命令。

jshell> /exit
|  終了します

$

如果在JShell中,当按下[Enter]键时,可以确定输入已经到了一个好的位置,那么JShell将执行该表达式。但是,如果输入在中途换行或者括号不完整等情况下结束得不完整,JShell将要求继续输入。

jshell> "test".repeat(
   ...>

当您输入长行时自行换行时并没有问题。但是,当您认为已经输入了一行但实际上括号不匹配导致行未结束时,这样的情况会很麻烦,有时重新输入会更快。在这种情况下,您可以使用[Ctrl]+[c]进行取消操作。

变量

顺便说一下,如果这个值接近于圆周率,我们可以用它来代替圆周率进行各种运算。据说古巴比伦时期就使用它作为圆周率。但是每次输22.0/7太麻烦了。

当我重新审视并计算22.0 / 7时,结果显示如下。

jshell> 22.0 / 7
$9 ==> 3.142857142857143

这表明可以使用值为9的名称。

jshell> $9
$9 ==> 3.142857142857143

然而,记住这个数字很麻烦。如果只有一个值那就好了,但是希望记住的值会不断增加。给值取个更容易记忆和理解含义的名字就很方便了。这就是变量的作用。变量可以通过var 变量名=值来定义。

jshell> var pi = 22.0 / 7
pi ==> 3.142857142857143

通过这段代码,变量pi被定义且被赋值为3.142857142857143。当输入pi时,会显示被赋值的值。

jshell> pi
pi ==> 3.142857142857143

我們將使用這個公式來計算半徑為5的圓的周長。圓的周長等於直徑乘以圓周率。我們可以將變數作為計算的值來使用。

jshell> 5*2*pi
$16 ==> 31.428571428571427

面积是半径乘以半径再乘以圆周率。

jshell> 5*5*pi
$17 ==> 78.57142857142857

以这种方式,可以使用变量来重复使用值。
顺便说一下,当在位置$17定义变量pi时,显示为pi。换句话说,这表示将78.57142857142857分配给变量$17。

jshell> $17
$17 ==> 78.57142857142857

顺便说一句,在Java中,实际上使用Math.PI可以保持较高精度的圆周率。

jshell> Math.PI
$82 ==> 3.141592653589793

Math类的PI字段,我们将在另外学习时详细讨论。

如果我们将这个值作为圆周率来使用,那么半径为5的圆的面积将会是如下的数值。

jshell> 5*5*Math.PI
$81 ==> 78.53981633974483

让我们将Math.PI分配给变量pi。

jshell> pi=Math.PI
pi ==> 3.141592653589793

如下所示,可以重新为变量分配值。
重新计算5*5*pi,结果与使用Math.PI得到的结果相同。

jshell> 5*5*pi
$84 ==> 78.53981633974483

变量的类型

让我们把一个字符串赋给先前提到的变量pi。

jshell> pi="circle ratio"
|  エラー:
|  不適合な型: java.lang.Stringをdoubleに変換できません:
|  pi="circle ratio"
|     ^------------^

出错了。提示无法将String转换为double。
在Java中,变量被分配的值的类型是确定的。这种类型的概念被称为“类型”。换句话说,变量的类型是确定的。
到目前为止,整数是int,小数是double,字符串是String。
那么,让我们来确认变量的类型。在JShell中,可以使用/var命令来确认变量的类型。

jshell> /var pi
|    double pi = 3.141592653589793

这表示变量pi的类型是double,并且被赋予了值3.141592653589793。double是处理实数的类型。

让我们来看看字符串的情况。首先,准备一个变量str,并为其分配字符串”circle”。

jshell> var str="circle"
str ==> "circle"

让我们使用/var命令来确认类型。

jshell> /var str
|    String str = "circle"

字符串被表示为String类型。这意味着字符串以String类型表示。
如果尝试分配实数,就会出现错误。

jshell> str=3.14
|  エラー:
|  不適合な型: doubleをjava.lang.Stringに変換できません:
|  str=3.14
|      ^--

到目前为止,我们一直使用var来声明变量。使用var可以自动确定变量的类型。在这里,也可以指定类型来声明变量。

jshell> String message="hello"
message ==> "hello"

而且,也可以对这种变量调用方法。

jshell> message.length()
$325 ==> 5

在中国,方法可以根据类型进行调用。length方法和repeat方法是为String类型准备的方法。而double类型没有可调用的方法。

也可以将方法返回的值赋给变量。

jshell> var count=message.length()
count ==> 5

在这里,变量count是int类型。

jshell> /var count
|    int count = 5

int类型是处理整数的数据类型。

练习:使用var,将实数1.414赋给变量root2。
练习:不使用var,将字符串”apple”赋给变量word。
练习:对上述准备好的word调用toUpperCase方法。

方法的定义

在Java中,可以通过定义方法来重复使用表达式,这对于类似半径乘以半径乘以圆周率的表达式非常方便。

请尝试运行一下稍长的代码:double menseki(double r){return r*r*pi;}

jshell> double menseki(double r){return r*r*pi;}
|  次を作成しました: メソッド menseki(double)

这样,面积方法已经被定义了。可以按照以下方式使用。

jshell> menseki(5)
$34 ==> 78.53981633974483

jshell> menseki(3)
$33 ==> 28.274333882308138

你可以重复使用这个表达式。

那么让我们稍微详细地看一下方法的定义。如果我们随意换行方法的定义,就会变成以下这样。

double menseki(double r) {
  return r*r*pi;
}

这个定义如下所示。

結果の型 メソッド名(引数の型 引数を扱う変数) {
  return 式;
}

这次定义了一个名为menseki的方法,接收实数并返回实数。使用变量r来接收传入的参数,r代表半径。在返回值时使用return语句。在这里,返回值是接收到的半径乘以2再乘以圆周率的结果。

在JShell中,您也可以通过换行来定义变量。

jshell> double menseki(double r) {
   ...>   return r*r*pi;
   ...> }
|  次を変更しました: メソッド menseki(double)

练习:参数的名称不一定要为r。请尝试定义一个与相同功能的方法menseki2,将参数命名为a。
练习:请定义一个接受半径并返回圆周长的方法。

摇摆

你有没有觉得光看文字很无聊呢?为了不只是看文字,我们来执行一些其他的东西吧。
我们将显示一个窗口。在Java中,已经准备了一个名为Swing的GUI工具包。GUI工具包是用于显示窗口和布置按钮等组件的部分。

显示窗口

首先准备一个窗口。

jshell> var f = new javax.swing.JFrame("test")
f ==> javax.swing.JFrame[fram ... bled=true]

我有点不太明白,但变量f已经被分配了某些内容。
接下来,我将调用show()方法。

jshell> f.show()
image.png
jshell> f.setSize(400,300)
image.png

类和对象

在创建窗口时,我执行了以下代码: var f = new javax.swing.JFrame(“test”)。
在Java中,我们将程序处理的窗口、按钮等对象称为“对象”。在这里,变量f被分配了一个窗口对象。Swing中使用javax.swing.JFrame类型来表示窗口。对象是基于某种类型生成的。用于生成对象的基本类型被称为“类”。javax.swing.JFrame就是一个类。

当从类中生成对象时,我们使用new运算符,并以new 类(参数)的方式生成。参数由类确定。

从某种角度来看,生成对象时似乎还在调用特殊的方法。我们称之为“构造函数”。构造函数是与类同名,需要通过new运算符进行调用的方法。

Java文档

javax.swing.JFrame的文档可以在此处找到:
https://docs.oracle.com/en/java/javase/18/docs/api/java.desktop/javax/swing/JFrame.html

如果你想使用日语的话,这是链接给你:
https://docs.oracle.com/javase/jp/17/docs/api/java.desktop/javax/swing/JFrame.html

这个文档的格式被称为「JavaDoc」。Java的API文档大多采用这个格式。

搜索「javadoc JFrame」等等,用javadoc + 类名即可找到大部分的JavaDoc。

スクリーンショット 2018-06-11 19.54.59.png

通过观察这段代码,我们可以知道在这里使用的是JFrame的构造函数(String title)。还提供了无参数的构造函数,因此可以生成没有指定标题的窗口。

可能需要更多的学习Java语言才能理解这些内容,但通过查阅JavaDoc可以了解到我们所写的代码的意义,并对Java语言有更好的理解。

另外,一般来说,解释书籍并不能解释所有内容,所以参考这种一手资料来准确地理解也非常重要。

练习:请在JavaDoc中查找之前使用过的String的replace方法。
提示:在右上角的搜索框中进行搜索会很方便。

包和导入

既然窗口已经能够显示出来了,那么我们就开始布置文本区域吧。文本区域是一个可以输入多行字符的组件。在Swing中,文本区域使用javax.swing.JTextArea类来处理。而将这样的组件放在窗口上,我们称之为”组件”。
为了布置文本区域,首先需要生成一个文本区域的对象。要生成对象,就要调用与类名相同的方法,也就是构造函数,在其前面加上new运算符。但是javax.swing.JTextArea这个名字太长,每次输入都很麻烦。
实际上,javax.swing.JTextArea被分为两部分,最后一个分隔符是类名,前面的部分是包名。也就是说javax.swing指的是javax.swing下的JTextArea类。”包”是Java中用来分类类的机制。

因此,使用import语句可以省略包名。例如,使用import javax.swing.*可以省略javax.swing包的包名,并只用类名表示。

jshell> import javax.swing.*

虽然我之前一直忽略了,但是我注意到了String类型会以java.lang.String的形式显示出来。String类型被包含在java.lang包中,由于预先进行了导入(import)操作,因此可以省略包名。

那么,让我们创建一个表示文本区域的JTextArea类的对象。

jshell> var textarea = new JTextArea()
textarea ==> javax.swing.JTextArea[,0,0,0x0,i ... rap=false]

需要将这个放置在窗口中。可以通过调用add方法将其添加到表示窗口的JFrame对象中。

jshell> f.add(textarea)
$14 ==> javax.swing.JTextArea[,0,0,0x0,inval ... se,wrap=false]

然而,如果不进行重新组织,它将不会显示在窗口上,因此需要重新组织窗口。通过调整窗口的大小,可以进行重新组织,可以尝试拖动窗口的边缘来改变大小,或者调用setSize方法。当使用setSize方法指定大小时,如果窗口大小没有改变,将不会执行任何操作,因此需要稍微调整大小。

jshell> f.setSize(400,301)

现在显示了文本区域,您可以输入文字。

image.png

对于文本输入框,您可以使用append方法来添加字符串。

jshell> textarea.append("te")

jshell> textarea.append("st")
image.png

换行用”\n”表示。(在Windows中用”¥n”表示)

jshell> textarea.append("\ntester\n")
image.png

添加按钮

好的,现在让我们来添加一个按钮。在 Swing 中,按钮是通过 JButton 类来处理的。你可以通过构造函数的参数来指定按钮的标签字符串。

jshell> var button = new JButton("Hello")
button ==> javax.swing.JButton[,0,0,0x0,inval...pable=true]
image.png

将第一个参数指定为添加位置,并将第二个参数指定为要添加的组件。

jshell> f.add("North", button)
$27 ==> javax.swing.JButton[,0,0,0x0,inval...ltCapable=true]

如果拼写错误了”North”这个词,就会出现这样的错误。请注意大小写的区别。

jshell> f.add("Nort", button)
|  Exception java.lang.IllegalArgumentException: cannot add to layout: unknown constraint: Nort
|        at BorderLayout.addLayoutComponent (BorderLayout.java:468)
|        at BorderLayout.addLayoutComponent (BorderLayout.java:429)
|        at JRootPane$1.addLayoutComponent (JRootPane.java:507)
|        at Container.addImpl (Container.java:1151)
|        at Container.add (Container.java:1028)
|        at JFrame.addImpl (JFrame.java:553)
|        at Container.add (Container.java:459)
|        at (#31:1)

顺便说一下,这个错误与以前试图将字符串赋给变量pi时发生的错误完全不同。它也不同于拼写错误添加add的情况。

jshell> f.ad("North", b)
|  エラー:
|  シンボルを見つけられません
|    シンボル:   メソッド ad(java.lang.String,javax.swing.JButton)
|    場所: タイプjavax.swing.JFrameの変数 f
|  f.ad("North", b)
|  ^--^

这些错误发生的时间不同,尝试为add或变量pi分配字符串时的错误是在解释程序时发生的错误,当错误地输入”North”时是在执行解释过的处理时发生的错误。
将解释程序时发生的错误称为编译错误,将运行时错误称为异常。
现在两种错误都在输入指令并按下回车键时发生,所以很难区分,但在实际开发中应该可以明确区分。现在,只要您能感受到错误有两种类型,就可以了。

话虽这样说,即使add操作成功执行,按钮仍然不会显示出来。
但是如果使用setSize方法重新构建窗口,按钮就会显示出来。

jshell> f.setSize(400,300)
image.png

但是,即使按下这个按钮也什么都不会发生。需要编写一些处理。请尝试以下输入方式。addActionListener有点长,但是输入addAc然后按下[tab]键,应该会自动补充剩下的。

jshell> button.addActionListener(ae -> textarea.append("Hello!\n"))
image.png

要添加按钮点击时的处理,需要使用addActionListener方法。
在这里,我们将参数ae->textarea.append(“Hello!\n”)指定为addActionListener方法。addActionListener方法需要传递一些处理,相当于“当按钮被点击时,请调用此处理”。这里的处理是textarea.append(“Hello!\n”),但如果要将处理作为值传递,需要使用类似“Lambda表达式”的方式。
Lambda表达式的写法如下。

引数 -> 処理

当按下按钮时,需要处理的情况下,将ActionEvent对象作为参数进行接收,在此处我们将其命名为ae,但如果可以理解,可以使用任何名称。我们目前没有使用接收到的参数。

从文本框接收输入

我们再多努力一点吧。
我会尝试做一个当按下按钮时,在文本框中显示输入的文本字符串的功能。
我想添加文本框和按钮,但在JFrame的布局方式下无法直接添加。因此,我将使用JPanel组件。

jshell> var panel = new JPanel()

jshell> f.add("South", panel)
image.png

添加文本字段。文本字段是一种只能输入一行的组件,使用JTextField组件。

jshell> var textfield = new JTextField()

jshell> textfield.setColumns(15)

jshell> panel.add(textfield)

通过 setColumns 方法设置宽度。

image.png
image.png

让我们最后尝试添加按钮。

jshell> var printButton = new JButton("Print")

jshell> printButton.addActionListener(ae -> textarea.append(textfield.getText() + "\n"))

jshell> panel.add(printButton)
image.png

练习:添加一个按钮,当点击时在文本区域显示”Yeah!”。
练习:添加一个按钮,将输入框中的字符串转换为大写字母,并将结果输出到文本区域。要将字符串中的字母转换为大写,可以使用toUpperCase方法。请先在JShell上尝试一下toUpperCase方法的使用方法。

离开 JShell 来编写 Java 程序

最后,让我们将之前在JShell中试验过的内容写成一个独立的Java程序。请在记事本或文本编辑器中输入以下源代码,并将其保存为名为”FirstWindow.java”的文件放置在桌面上。

import javax.swing.*;

public class FirstWindow {
  public static void main(String... args) {
    var frame = new JFrame("test");

    var textarea = new JTextArea();
    frame.add(textarea);

    var textfield = new JTextField();
    textfield.setColumns(15);
    var button = new JButton("Print");
    button.addActionListener(ae -> textarea.append(textfield.getText() + "\n"));

    var panel = new JPanel();
    panel.add(textfield);
    panel.add(button);
    frame.add("North", panel);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.show();
  }
}

在JShell中添加了一些之前没有的内容。此外,输入到JShell的命令后面都有分号(semicolon)。但是,与开始这个教程之前相比,你可能会有一种“我能读懂了!”的感觉,对吗?

现在,让我们尝试运行这段源代码。
请打开命令提示符。这次不使用JShell。
使用cd命令切换到桌面。

$ cd Desktop

接着,使用javac命令编译先前输入的源代码。

$ javac FirstWindow.java

如果发生错误,请进行更正并保存,然后再进行编译。
当错误消失时,请检查所创建的文件。
在Windows中使用dir命令,在Mac和Linux中使用ls命令。

$ dir FirstWindow.*

第一個視窗的.class檔案已經建立了,這就是Java的執行程式碼。要執行它,我們需要使用java命令。

$ java FirstWindow
image.png

请从这里开始进行Java的深入学习。

bannerAds