一、与用户互动
绝大部分程序需要处理用户动作,包括接收用户的键盘输入、鼠标动作等。
1.运行Java程序的参数
// Java程序入口:main()方法
public static void main(String[] args){...}
那main()方法为什么采用这个方法签名呢?
- public修饰符:Java类有JVM调用,为了让JVM可以自由调用这个main()方法,所以使用public修饰符把这个方法暴露出来。
- static修饰符:JVM调用这个主方法时,还没有该类的对象,因此只能通过该类直接调用主方法,因此使用static修饰该主方法。
- void返回值:因为主方法被JVM调用,该方法的返回值将返回给JVM,这没有任何意义,因此main()方法没有返回值。
上面的方法中还包括一个字符串数组形参,根据方法调用的规则:谁调用方法,谁负责为形参赋值。也就是说,main()方法有JVM调用,即args形参应该由JVM负责赋值。但JVM怎么知道如何为args数组赋值呢?先看下面的程序。
public class ArgsTest
{
public static void main(String[] args)
{
// 输出args数组的长度
System.out.println(args.length);
// 遍历args数组的每个元素
for(String arg : args)
{
System.out.prinln(arg);
}
}
}
在cmd编译后执行java ArgsTest
命令,看到程序仅仅输出一个0,这表明args数组是一个长度为0的数组。
改为如下命令来运行上面程序:
java ArgsTest Java Spring
将看到如下运行结果:
从上图可以看出,如果运行Java程序时在类名后紧跟一个或多个字符串(多个字符串之间以空格隔开),JVM就会把这些字符串依次赋给args数组元素。运行Java程序时的参数与args数组之间的对应关系如下:
如果某参数本身包含了空格,则应该将该参数用双引号(“”)括起来,否则JVM会把这个空格当成参数分隔符,而不是当成参数本身。
2.使用Scanner获取键盘输入
Scanner类可以很方便地获取用户的键盘输入,是一个基于正则表达式的文本扫描器,它可以从文件、输入流、字符串中解析出基本类型值和字符串值。Scanner类提供了多个构造器,不同的构造器可以接受文件、输入流、字符串作为数据源,用于从文件、输入流、字符串中解析数据。
Scanner主要提供了两个方法来扫描输入。
-
**hasNextXxx()😗*是否还有下一个输入项,其中Xxx可以是Int、Long等代表基本数据类型的字符串。如果只是判断是否包含下一个字符串、则直接使用hasNext()。
-
**nextXxx()😗*获取下一个输入项。Xxx的含义与前一个方法中的Xxx相同。
在默认情况下,Scanner使用空白(包括空格、Tab空白、回车)作为多个输入项之间的分隔符。
为Scanner设置分隔符使用userDelimiter(String pattern)方法即可,例如使用sc.useDelimiter("\n");
将只把回车作为分隔符,sc是一个Scanner对象。
事实上,Scanner提供了两个简单的方法来逐行读取。 -
boolean hasNextLine(): 返回输入源中是否还有下一行。
-
String nextLine(): 返回输入源中下一行的字符串。
Scanner不仅能读取用户的键盘输入,还可以读取文件输入。只要在创建Scanner对象时传入一个File对象作为参数,就可以让Scanner读取该文件的内容。
Scanner sc = new Scanner(new File("filepath"));
二.系统相关
Java程序在不同操作系统上运行时,可能需要取得平台相关的属性,或者调用平台命令来完成特定功能。Java提供了System类和Runtime类来与程序的运行平台进行交互。
1.System类
System类代表当前Java程序的运行平台,程序不能创建System类的对象,System类提供了一些类变量和类方法,允许直接通过System类来调用这些类变量和类方法。
System类提供了代表标准输入、标准输出和错误输出的类变量,并提供了一些静态方法用于访问环境变量、系统属性的方法,还提供了加载文件和动态链接库的方法,以及通知系统进行垃圾回收的方法、通知系统进行资源清理的方法。getenv(); getProperties(); getProperty(); gc(); runFinalization()
System类还有两个获取系统当前时间的方法:currentTimeMillis()
和nanoTime()
。他们都返回一个long型整数。实际上他们都返回当前时间与UTC 1970年1月1日午夜的时间差,前者以毫秒作为单位,后者以纳秒作为单位。必须指出的是,这两个方法返回的时间粒度取决于底层操作系统,可能所在的操作系统根本不支持以毫秒、纳秒作为计时单位。
除此之外,System类的in、out、err分别代表系统的标准输入(通常是键盘)、标准输出(通常是显示器)和错误输出流,并提供了setIn(); setOut(); setErr()
方法来改变系统的标准输入、标准输出和标准错误输出流。
System类还提供了一个identityHashCode(Object x)方法,该方法返回指定对象的精确hashCode值,也就是根据该对象的地址计算得到的hashCode值。当某个类的hashCode()方法被重写后,该类实例的hashCode()方法就不能唯一地标识该对象;但通过identityHashCode()方法返回的hashCode值,依然是根据该对象的地址计算得到的hashCode值。所以如果两个对象的identityHashCode值相同,则两个对象绝对是同一个对象。
2.Runtime类
Runtime类代表Java程序的运行时环境,每个Java程序都有一个与之对应的Runtime实例,应用程序通过该对象与其运行时环境相连。应用程序不能创建自己的Runtime实例,但可以通过getRuntime()方法获取与之关联的Runtime对象。
与System类似的是,Runtime也提供了gc()方法和runFinalization()方法来通知系统进行垃圾回收、清理系统资源,并提供了load(String filename)和load(String libname)方法来加载文件和动态链接库。
Runtime类代表Java程序的运行时环境,可以访问JVM的相关信息,如处理器数量、内存信息等。
除此之外,Runtime类还有一个功能——它可以直接单独启动一个进程来运行操作系统的命令。Runtime提供了一系列exec();
方法来运行操作系统命令。