《疯狂java讲义》学习(21):与用户互动

版权声明:本文为博主原创文章,如若转载请注明出处 https://blog.csdn.net/tonydz0523/article/details/86593064

与用户互动

如果一个程序总是按既定的流程运行,无需处理用户动作,这个程序总是比较简单的。实际上,绝大部分程序都需要处理用户动作,包括接受用户的键盘输入、鼠标动作等。因为现在还未涉及图像用户接口(GUI)编程,这里讲述程序如何获得用户的键盘输入。

运行Java程序的参数

会议Java程序的入门——main方法的方法签名:

// Java程序入口: main方法
public static void main(String[] args){....}

这里解释main方法为什么采用这个方法签名:

  • public修饰符:Java类由JVM调用,为了让JVM可以自由调用这个main方法,所以使用public修饰符把这个方法暴露出来。
  • static修饰符:JVM调用这个主方法时,不会先创建该主类的对象,然后通过对象来调用该主方法。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.println(arg);
        }
    }
}

上面程序几乎是最简单的“HelloWorld”程序,只是这个程序增加了输出args数组的长度,遍历args数组元素的代码。使用java ArgsTest命令运行上面程序,看到程序仅仅输出一个0,这表明args数组是一个长度为0的空数组——这是合理的。因为计算机是没有思考能力的,它只能忠实地执行用户交给它的任务,既然我们没有给args数组设定参数值,那么JVM就不知道args数组的元素,所以JVM将args数组设置成一个长度为0的数组。
如果某参数本身包含了空格,则应该将该参数用双引号("")括起来,否则JVM会把这个空格当成参数分隔符,而不是当成参数本身。例如,采用如下命令来运行上面程序:
java ArgsTest "Java Spring"
看到args数组的长度是1,只有一个数组元素,其值是Java Spring。

使用Scanner获取键盘输入

运行Java程序时传入参数只能在程序开始运行之前就设定几个固定的参数。对于更复杂的情形,程序需要在运行过程中取得输入。
使用Scanner类可以很方便的获取用户的键盘输入,Scanner是一个机遇正则表达式的文本扫面器,它可以从文件、输入流、字符串中解析出基本类型值和就收文件、输入流、字符串作为数据源,用于从文件、输入流、字符串中解析数据。
Scanner主要提供了两个方法来扫描输入:

  • hasNextXxx():是否还有下一个输入项,其中Xxx可以是Int、Long等代表基本数据类型的字符串。如果需要判断是否包含下一个字符串,则可以省略Xxx。
  • nextXxx():获取下一个输入项。Xxx的含义与前一个方法中的Xxx相同。

在默认情况下,Scanner使用空白(包括空格、Tab空白、回车)作为多个输入项之间的分隔符。下面程序使用Scanner来获得用户的键盘输入:

import java.util.Scanner;

public class ScannerKeyBoardTest {
    public static void main(String[] args){
        //System.in 代表标准输入,就是键盘输入
        Scanner sc=new Scanner(System.in);
        //增加下面一行将只把回车作为分割符
        sc.useDelimiter("\n");
        //判断是否还有下一个输入项
        while(sc.hasNext()){
            //输出输入项
            System.out.println("键盘输入的内容是:"+ sc.next());
        }
    }
}

运行上面程序,程序通过Scanner不断从键盘读取键盘输入,每次读到键盘输入后,直接将输入内容打印在控制台。
如果希望改变Scanner的分隔符(不使用空白作为分割符),例如,程序需要每次读取一行,不管这一行中时都包含空格,Scanner都把它当成一个输入项。在这种需求下,我们可以把Scanner的分割符设置为回车符,不再使用默认的空白作为分隔符。
Scanner的读取操作可能被阻塞(当前执行顺序流暂停)来等待信息的输入。如果输入源没有结束,Scanner又读不到更多输入项时(尤其在键盘输入时比较常见),Scanner的hasNext()和next()方法都有可能阻塞,hasNext()方法是否阻塞与和其他相关的next()方法是否阻塞无关。
为Scanner设置分割符使用useDelimiter(String pattern)方法即可,该方法的参数应该是一个正则表达式。
事实上,Scanner提供了两个简单的方法来逐行读取。

  • boolean hasNextLine():返回输入源中是否还有下一行。
  • String nextLine():返回输入源中下一行的字符串。
    Scanner不仅可以获取字符串输入项,也可以获取任何基本类型的输入项,如下程序所示:
import java.util.Scanner;

public class ScannerLongTest {
    public static void main(String[] args){
        //System.in代表标准输入,就是键盘输入
        Scanner sc=new Scanner(System.in);
        //判断是否有下一个long整数
        while(sc.hasNextLong()){
            //输出输入项
            System.out.println("键盘输入的内容是:"+sc.nextLong());
        }
    }
}

注意上面程序中粗体字代码部分,正如通过hasNextLong()和nextLong()两个方法,Scanner可以直接从输入流中获得long型整数输入项。与此类似的是,如果需要获取其他基本类型的输入项,则可以使用相应的方法。
Scanner不仅能读取用户的键盘输入,还可以读取文件输入。只要在创建Scanner对象时传入一个File对象作为参数,就可以让Scanner读取该文件的内容:

import java.io.File;
import java.util.Scanner;

public class ScannerFileTest
{
    public static void main(String[] args)
            throws Exception
    {
        //将一个File对象作为Scanner的构造器参数,Scanner读取文件内容
        Scanner sc=new Scanner(new File("ScannerFileTest.java"));
        System.out.println("ScannerFileTest.java文件内容如下:");
        //判断是否还有下一行
        while(sc.hasNextLine()){
        //输出文件中的下一行
        System.out.println(sc.nextLine());
         }
    }
}

上面程序创建Scanner对象时传入一个File对象作为参数。

使用BufferedReader获取键盘输入

Scanner可以非常方便地获取键盘输入,在Java5之前,程序通常使用BufferedReader类来读取键盘输入。
BufferedReader是Java IO流中的一个字符、包装流,它必须建立在另一个字符流的基础之上。但标准输入:System.in是字节流,程序需要使用转换流InputStreamReader将其包装成字符流。
一旦获得了BufferedReader对象之后,就可以调用该对象的readLine()方法来逐行读取键盘输入;如果没有键盘输入,readLine()方法将会阻塞来等待键盘输入。如下程序所示:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class KeyboardInTest {
    public static void main(String[] args)
        throws Exception{
        //以System.in字节流作为基础,创建一个BufferReader对象
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String line=null;
        //逐行读取键盘输入
        while ((line=br.readLine())!=null){
            System.out.println("用户键盘输入是:"+line);
        }
    }
}

使用BufferedReader可以逐行读取用户的键盘输入,用户的每次键盘输入都被BufferedReader当成String对象。与Scanner不同的是,BufferedReader不能读取基本类型输入项,它总是读取String对象。

java实例练习

将数字格式化为货币字符串

数字可以标识货币、百分比、积分、电话号码等。就货币而言,在不同的国家里会以不同的格式来定义。本实例将通过接收用户输入的数字,将这个数字转换为不同国家的货币格式,然后在控制台中输出这些货币的格式。

1.

新建项目CurrencyFormat,并在其中创建一个CurrencyFormat.java文件。在该类的主方法中创建标准输入流的扫描器对象,接收用户输入的数字,通过NumberFormat类的format()方法把接收的数字格式转换为货币字符串:

package CurrencyFormat;

import java.text.NumberFormat;
import java.util.Locale;
import java.util.Scanner;

public class CurrencyFormat {
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);   //创建标注输入流扫描器
        System.out.println("请输入一个数字:");
        double number = scan.nextDouble();   //获取用户输入数字
        System.out.println("改数字用Locale类的以下常量作为格式化对象的构造参数,将获得不同的货币格式:");  //创建格式化对象
        NumberFormat format = NumberFormat.getCurrencyInstance(Locale.CHINA);   //输出格式化货币格式
        System.out.println("Locale.CHINA:" + format.format(number));
        format = NumberFormat.getCurrencyInstance(Locale.ENGLISH);
        System.out.println("Locale.ENGLISH:" + format.format(number));
    }
}

数字格式化是本案例的关键点,实例中应用NumberFormat类实现了数字格式化,这个类时一个抽象类,但是可以通过其静态方法获取内部实现类的实例对象,本实例获取了货币的格式对象。
格式化对象可以指定语言环境,在Java中使用Local类的对象来表示,在该类中包含了三个语言环境。通过它可以获取国际化的字符串信息,如货币、时间等。

实现不同字符串的连接

字符串连接是程序中经常进行的操作,用来将多个字符串来接在一起形成一个字符串。我们可以使用加法(+)运算符或是append()方法来实现这种连接。

1.

新建项目StringConnection,并在其中创建一个StringConnection.java文件。在该类的主方法中创建三种字符串的连接方法,实现对不同字符串的连接。核心代码如下所示:

package StringConnection;

public class StringConnection {
    public static void main(String[] args){
        String s1 = "hello" + ", " + "world";
        System.out.println("使用加法运算符输出:" + s1);
        // 构造StringBuffer对象,并添加一些字符串
        StringBuffer sb2=new StringBuffer();
        sb2.append("hello");   //使用
        sb2.append(",");
        sb2.append(' ');
        sb2.append("world");
        // 将StringBuffer值转换为字符串,并输出
        String s2 = sb2.toString();
        System.out.println("使用append()方法输出:" + s2);
        // 重复上面的工作使用更简单的方法
        StringBuffer sb3=new StringBuffer().append("hello").append(',').append(' ').append("world");
        System.out.println("append()方法的另一种形式输出:" + sb3.toString());

    }
}

猜你喜欢

转载自blog.csdn.net/tonydz0523/article/details/86593064