1 编写RegExUtils类,提供静态方法实现对身份证号码、邮政编码、手机号码的合法性校验

参考答案

在企业的项目中,我们通常也会构建一些工具类,用于专门的用途。这些类,大多以XxxUtils作为命名。例如当前案例中要求的RegUtils,主要用于使用正则表达式验证各种信息是否合法。要实现当前案例的需求,需要以下步骤:

首先,构建RegExUtils类,在该类中添加静态常量IDENTITY_CARD、ZIP_CODE以及PHONE_NUMBER分别表示身份证号码、邮政编码以及手机号码的正则表达式。

其次,在RegUtils类中,定义check方法,该方法用于检查字符串str是否和正则表达式regex匹配。

最后,在RegExUtils类中,添加方法identityCard、zipcode以及phoneNumber分别用于实现检测身份证号码、邮政编码以及手机号码是否为合法的。

实现此案例需要按照如下步骤进行。

步骤一:构建工具类RegUtils

在工程JavaSE中,新建类RegExUtils,代码如下所示:

package day02;

public class RegExUtils {

}

步骤二:定义静态常量表示正则表达式

在RegExUtils类中,添加静态常量IDENTITY_CARD、ZIP_CODE以及PHONE_NUMBER分别表示验证身份证号码、邮政编码以及手机号码的正则表达式,代码如下所示:

package day02;

public class RegExUtils {
#cold_bold	//验证身份证号码的正则表达式
#cold_bold	private static final String IDENTITY_CARD = "^\\d{15}|\\d{18}$";
#cold_bold	//验证邮政编码的正则表达式
#cold_bold	private static final String ZIP_CODE = "^[1-9][0-9]{5}$";
#cold_bold	//正则手机号码的正则表达式
#cold_bold	private static final String PHONE_NUMBER = "^13[0-9]{9})|(15[89][0-9]{8}$";
}

对于上述正则表达式能看懂即可。

步骤三:构建检查字符串str是否和正则表达式匹配的方法check

在RegExUtils类中,定义check方法,该方法用于检查字符串str是否和正则表达式regex匹配,代码如下所示:

package day02;

public class RegExUtils {

	//验证身份证号码的正则表达式
	private static final String IDENTITY_CARD = "^\\d{15}|\\d{18}$";
	//验证邮政编码的正则表达式
	private static final String ZIP_CODE = "^[1-9][0-9]{5}$";
	//正则手机号码的正则表达式
	private static final String PHONE_NUMBER = "^13[0-9]{9})|(15[89][0-9]{8}$";

#cold_bold	/**
#cold_bold	 * 检查字符串str是否和正则表达式regex匹配
#cold_bold	 * 
#cold_bold	 * @param str
#cold_bold	 *            字符串
#cold_bold	 * @param regex
#cold_bold	 *            正则表达式
#cold_bold	 * @return 如果字符串str和正则表达式regex匹配,返回true,否则,返回false
#cold_bold	 */
#cold_bold	private static boolean check(String str, String regex) {
#cold_bold		return str.matches(regex);
#cold_bold	}
}

步骤四:检查

在RegExUtils类中,添加方法identityCard、zipcode以及phoneNumber分别用于实现检测身份证号码、邮政编码以及手机号码是否为合法的,代码如下所示:

package day02;

public class RegExUtils {
	//验证身份证号码的正则表达式
	private static final String IDENTITY_CARD = "^\\d{15}|\\d{18}$";
	//验证邮政编码的正则表达式
	private static final String ZIP_CODE = "^[1-9][0-9]{5}$";
	//正则手机号码的正则表达式
	private static final String PHONE_NUMBER = "^13[0-9]{9})|(15[89][0-9]{8}$";

	/**
	 * 检查字符串str是否和正则表达式regex匹配
	 * 
	 * @param str
	 *            字符串
	 * @param regex
	 *            正则表达式
	 * @return 如果字符串str和正则表达式regex匹配,返回true,否则,返回false
	 */
	private static boolean check(String str, String regex) {
		return str.matches(regex);
	}

#cold_bold
#cold_bold	/**
#cold_bold	 * 检测是否为合法的身份证号码
#cold_bold	 * 
#cold_bold	 * @param str
#cold_bold	 *            身份证号码字符串
#cold_bold	 * @return 如果身份证号码字符串和正则表达式匹配则返回true,否则返回false
#cold_bold	 */
#cold_bold	public static boolean identityCard(String str) {
#cold_bold		return check(str, IDENTITY_CARD);
#cold_bold	}
#cold_bold
#cold_bold	/**
#cold_bold	 * 检测是否为合法的邮政编码
#cold_bold	 * 
#cold_bold	 * @param str
#cold_bold	 *            邮政编码字符串
#cold_bold	 * @return 如果邮政编码字符串和正则表达式匹配则返回true,否则返回false
#cold_bold	 */
#cold_bold	public static boolean zipcode(String str) {
#cold_bold		return check(str, ZIP_CODE);
#cold_bold	}
#cold_bold
#cold_bold	/**
#cold_bold	 * 检测是否为合法的手机号码
#cold_bold	 * 
#cold_bold	 * @param str
#cold_bold	 *            手机号码字符串
#cold_bold	 * @return 如果手机号码字符串和正则表达式匹配则返回true,否则返回false
#cold_bold	 */
#cold_bold	public static boolean phoneNumber(String str) {
#cold_bold		return check(str, PHONE_NUMBER);
#cold_bold	}
}

观察上述方法,可以看出,在上述方法中都调用了步骤二定义check方法,check方法的重用率很高,这也是单独定义check方法的原因。

本案例中,RegExUtils的完整代码如下所示:

package day02;

public class RegExUtils {

	//验证身份证号码的正则表达式
	private static final String IDENTITY_CARD = "^\\d{15}|\\d{18}$";
	//验证邮政编码的正则表达式
	private static final String ZIP_CODE = "^[1-9][0-9]{5}$";
	//正则手机号码的正则表达式
	private static final String PHONE_NUMBER = "^13[0-9]{9})|(15[89][0-9]{8}$";

	/**
	 * 检查字符串str是否和正则表达式regex匹配
	 * 
	 * @param str
	 *            字符串
	 * @param regex
	 *            正则表达式
	 * @return 如果字符串str和正则表达式regex匹配,返回true,否则,返回false
	 */
	private static boolean check(String str, String regex) {
		return str.matches(regex);
	}


	/**
	 * 检测是否为合法的身份证号码
	 * 
	 * @param str
	 *            身份证号码字符串
	 * @return 如果身份证号码字符串和正则表达式匹配则返回true,否则返回false
	 */
	public static boolean identityCard(String str) {
		return check(str, IDENTITY_CARD);
	}

	/**
	 * 检测是否为合法的邮政编码
	 * 
	 * @param str
	 *            邮政编码字符串
	 * @return 如果邮政编码字符串和正则表达式匹配则返回true,否则返回false
	 */
	public static boolean zipcode(String str) {
		return check(str, ZIP_CODE);
	}

	/**
	 * 检测是否为合法的手机号码
	 * 
	 * @param str
	 *            手机号码字符串
	 * @return 如果手机号码字符串和正则表达式匹配则返回true,否则返回false
	 */
	public static boolean phoneNumber(String str) {
		return check(str, PHONE_NUMBER);
	}
}

2 重写员工类(Emp)的equals和toString方法

在面向对象的课程中,我们曾使用过Emp类,本案例要求重写Emp类的toString方法和equals方法,详细要求如下:

1),重写Emp类的toString方法,返回Emp对象的名字、年龄、性别和工资信息,例如:张三,23,男,5000。

2),重写Emp类的equals方法,两个Emp引用变量相等的条件是名字相等。

参考答案

实现此案例需要按照如下步骤进行。

步骤一:创建 Emp类

创建 Emp类,并在其中覆盖toString方法,返回Emp对象的名字,年龄,性别和工资信息,代码如下所示:

package day02;

public class Emp {
	String name;
	int age;
	char gender;
	double salary;

	public void printInfo() {
		System.out.println("--------------------");
		System.out.println("姓名: " + name);
		System.out.println("年龄:" + age);
		System.out.println("性别:" + gender);
		System.out.println("薪水:" + salary);
	}

	@Override
	public String toString() {
		return name + "," + age + "," + gender + "," + salary;
	}
}

步骤二:写测试方法

测试toString方法是否覆盖生效。首先,在JavaSE工程下的day02包下新建TestEmp,然后,在该类中添加测试方法testToString,最后,实例化一个Emp类的对象,其name、age、gender、salary为张三、23、男、5000,并输出该对象,代码如下所示:

package day02;

import org.junit.Test;

public class TestEmp {
	/**
	 * 测试toString方法
	 */
	@Test
	public void testToString() {
		Emp emp = new Emp();
		emp.name="张三";
		emp.age=23;
		emp.gender='男';
		emp.salary=5000;
		System.out.println(emp); // 张三,23,男,5000
	}
}

步骤三:运行

运行testToString方法,控制台输出结果如下所示:

张三,23,男,5000

从运行结果可以看出,已经成功覆盖了toString方法,返回name、age、gender、salary的值为张三,23,男,5000。

步骤四:在Emp类中覆盖equals方法

在Emp类中覆盖equals方法,两个Emp引用变量相等的条件是名字相等,代码如下所示:

package day02;

public class Emp {
	String name;
	int age;
	char gender;
	double salary;

	public void printInfo() {
		System.out.println("--------------------");
		System.out.println("姓名: " + name);
		System.out.println("年龄:" + age);
		System.out.println("性别:" + gender);
		System.out.println("薪水:" + salary);
	}

	@Override
	public String toString() {
		return name + "," + age + "," + gender + "," + salary;
	}

#cold_bold	@Override
#cold_bold	public boolean equals(Object obj) {
#cold_bold		if (obj == null) {
#cold_bold			return false;
#cold_bold		}
#cold_bold		if (this == obj) {
#cold_bold			return true;
#cold_bold		}
#cold_bold		if (obj instanceof Emp) {
#cold_bold			Emp emp = (Emp) obj;
#cold_bold			return this.name.equals(emp.name);
#cold_bold		} else {
#cold_bold			return false;
#cold_bold		}
#cold_bold	}
}

此处需要注意,属性name的类型为String类型,比较两个字符序列是否相等使用equals方法。

步骤五:测试equals方法是否生效

测试equals方法是否覆盖生效。首先,在类TestEmp中添加测试方法testEquals,然后,创建emp1对象和emp2对象; 最后,分别使用==和equals比较emp1对象和emp2对象是否相等,代码如下所示:

package day02;

import org.junit.Test;

public class TestEmp {
	/**
	 * 测试toString方法
	 */
	@Test
	public void testToString() {
		Emp emp = new Emp();
		emp.name="张三";
		emp.age=23;
		emp.gender='男';
		emp.salary=5000;
		System.out.println(emp); // 张三,23,男,5000
	}

#cold_bold	/**
#cold_bold	 * 测试equals方法
#cold_bold	 */
#cold_bold	@Test
#cold_bold	public void testEquals() {
#cold_bold		Emp emp1 = new Emp();
#cold_bold		emp1.name="张三";
#cold_bold		emp1.age=24;
#cold_bold		emp1.gender='女';
#cold_bold		emp1.salary=6000;
#cold_bold		Emp emp2 = new Emp();
#cold_bold		emp2.name="张三";
#cold_bold		emp2.age=23;
#cold_bold		emp2.gender='男';
#cold_bold		emp2.salary=5000;
#cold_bold		System.out.println(emp1 == emp2); // false
#cold_bold		System.out.println(emp1.equals(emp2)); // true
#cold_bold	}
}

步骤六:运行

运行testEquals方法,控制台输出结果如下所示:

false
true

从运行结果可以看出,使用==比较的结果为false、使用equals比较的结果为true,说明Emp类成功覆盖了equals方法,实现了名字(name)相等两个Emp的引用变量则相等。

本案例中,Emp类的完整代码如下所示:

package day02;

public class Emp {
	String name;
	int age;
	char gender;
	double salary;

	public void printInfo() {
		System.out.println("--------------------");
		System.out.println("姓名: " + name);
		System.out.println("年龄:" + age);
		System.out.println("性别:" + gender);
		System.out.println("薪水:" + salary);
	}

	@Override
	public String toString() {
		return name + "," + age + "," + gender + "," + salary;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (this == obj) {
			return true;
		}
		if (obj instanceof Emp) {
			Emp emp = (Emp) obj;
			return this.name.equals(emp.name);
		} else {
			return false;
		}
	}
}

TestEmp类的完整代码如下:

package day02;

import org.junit.Test;

public class TestEmp {
	/**
	 * 测试toString方法
	 */
	@Test
	public void testToString() {
		Emp emp = new Emp();
		emp.name="张三";
		emp.age=23;
		emp.gender='男';
		emp.salary=5000;
		System.out.println(emp); // 张三,23,男,5000
	}

	/**
	 * 测试equals方法
	 */
	@Test
	public void testEquals() {
		Emp emp1 = new Emp();
		emp1.name="张三";
		emp1.age=24;
		emp1.gender='女';
		emp1.salary=6000;
		Emp emp2 = new Emp();
		emp2.name="张三";
		emp2.age=23;
		emp2.gender='男';
		emp2.salary=5000;
		System.out.println(emp1 == emp2); // false
		System.out.println(emp1.equals(emp2)); // true
	}
}

3 输入数字字符串,转换为整数或浮点数

用户从控制台接收一个字符串,通过程序判断该字符串是整数,还是小数。如果既不是整数也不是小数,程序输出“数字格式不正确”。程序交互过程如下所示:

用户输入整数字符串的情况,如图-1所示:

图- 1

用户输入为小数的情况,如图-2所示:

图- 2

用户输入的既不是整数也不是小数的情况,如图-3所示:

图- 3

参考答案

实现此案例需要按照如下步骤进行。

步骤一:新建TestChange类,添加testStringToIntOrDouble方法

首先,在工程JavaSE的day02包下新建类TestChange;然后,在该类中添加方法testStringToIntOrDouble,代码如下所示:

package day02;

import java.util.Scanner;
import org.junit.Test;

public class TestChange {
	@Test
	public void testStringToIntOrDouble() {
	}
}

步骤二:定义正则表达式

定义匹配整数和匹配小数的正则表达式,代码如下所示:

package day02;

import org.junit.Test;
public class TestChange {
	@Test
	public void testStringToIntOrDouble() {
#cold_bold		String integerRegex = "^[0-9]+$";
#cold_bold		String decimalRegex = "^[0-9]+\\.[0-9]+$";
	}
}

步骤三:对用户输入的字符串进行判断

首先,接收用户输入的字符串;然后,使用字符串的matches方法判断该字符串是整数还是小数或是其它情况,代码如下所示:

package day02;

import java.util.Scanner;
import org.junit.Test;

public class TestChange {
	@Test
	public void testStringToIntOrDouble() {
		String integerRegex = "^[0-9]+$";
		String decimalRegex = "^[0-9]+\\.[0-9]+$";
#cold_bold		Scanner scanner = new Scanner(System.in);
#cold_bold		System.out.println("请输入一个数字:");
#cold_bold		String numberStr = scanner.nextLine();
#cold_bold		if(numberStr.matches(integerRegex)){
#cold_bold			System.out.println("这是一个整数:"+Integer.parseInt(numberStr));
#cold_bold		}else if(numberStr.matches(decimalRegex)){
#cold_bold			System.out.println("这是一个小数:"+Double.parseDouble(numberStr));
#cold_bold		}else{
#cold_bold			System.out.println("数字格式不正确!");
#cold_bold		}
	}
}

上述代码中,使用Integer的parseInt方法将字符串转换为整数、使用Double的parseDouble方法将字符串转换为浮点数。

本案例的完整代码如下所示:

package day02;

import java.util.Scanner;
import org.junit.Test;

public class TestChange {
	@Test
	public void testStringToIntOrDouble() {
		String integerRegex = "^[0-9]+$";
		String decimalRegex = "^[0-9]+\\.[0-9]+$";
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入一个数字:");
		String numberStr = scanner.nextLine();
		if(numberStr.matches(integerRegex)){
			System.out.println("这是一个整数:"+Integer.parseInt(numberStr));
		}else if(numberStr.matches(decimalRegex)){
			System.out.println("这是一个小数:"+Double.parseDouble(numberStr));
		}else{
			System.out.println("数字格式不正确!");
		}
	}
}

4 简述自动装箱和拆箱的原理

参考答案

装箱和拆箱是 “编译器”认可的,而不是虚拟机。编译器在生成类的字节码时,插入必要的方法调用,例如:

将自动装箱处理为:

Integer a  = 100  =>  Integer a = Integer.valueOf(100)
Integer b  = 200  =>  Integer b = Integer.valueOf(200)
Integer c = a +b  => 
      Integer c = Integer.valueOf (a.intValue( ) + b.intValue( ))

可以看出,自动装箱时,调用了Integer的valueOf方法将int类型的值100转换成了Integer类型。

自动拆箱处理为:

int d = c        =>   int d  = c . intValue( )

可以看出,自动拆箱时,调用了Integer的intValue方法,将Integer类型的变量转成了int类型。