第二次Blog作业总结02
第二次Blog作业总结02
一 、前言
题目集4~6:
题目集4:主要知识点涉及:使用Java中的字符串处理类以及正则表达式对输入字符串数据进行合法性校验及计算,日期问题面向对象设计(聚合一),类的继承。
题目集5主要知识点涉及:字符串的查找,数组的合并,3中对数据的排序算法:插入排序、选择排序、冒泡排序,使用List、Set或Map中一种或多种,日期问题面向对象设计(聚合二)。
题目集6主要知识点涉及:正则表达式的训练,字符串训练,图形继承与多态性,图形接口及多态性;类的封装性、继承性和多态性。
题目集的题目数量总体不变,难度由易入难,逐渐递增。
二 、设计与分析
题目集 4(7-1):水文数据校检及处理
具体内容如下:
使用Java中的字符串处理类以及正则表达式对输入字符串数据进行合法性校验及计算。假定分水口门的数据上报时是采用人工输入的方式,每一行代表一个整点时刻的分水数据,各数据之间采用“|”符号进行分隔,每次可以输入多条数据,直到遇到用户输入“exit”为止,每一行输入数据共包含五部分:测量时间、目标水位、实际水位、开度(包含目标开度和实际开度,以“/”分隔)、流量。 各数据格式要求如下:
测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分”始终保持两位,且始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
目标开度、实际开度:实型数,取值范围为[1,10),必须保留2位小数,两个开度之间用“/”分隔
代码如下:
import java.util.Scanner;
public class Main {
//记录是否全为合法数据
static int mark=0;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String s=null;
int cnt=0;
//记录总流量
double sum=0;
//记录最大实际水位
double mmax=0;
while(!(s=in.nextLine()).equals("exit")){
//记录行数
cnt++;
if(s.length()==0) continue;
//预处理字符串,返回分割后字符串数组
String [] arrayString=Preprocessing(s);
//检验整体合法
if(!checkArray(arrayString)){
System.out.println("Wrong Format");
System.out.println("Data:"+s);
continue;
}
//如果分隔合法,则对各数据进行分别进行合法检验,如果返回值为真进行,加入总流量中
if(checkArrayAll(arrayString,cnt,s)) {
sum += Double.valueOf(arrayString[4]) * 60 * 60 * 2;
mmax= Math.max(mmax,Double.valueOf(arrayString[2]));
}
}
if(mark==0){
System.out.printf("Max Actual Water Level:%.2f\n",mmax);
System.out.printf("Total Water Flow:%.2f\n",sum);
}
}
//去除两端空格,同时根据|来切开字符串,检验该数据是否是由|分开的5部分
public static String []Preprocessing(String s){
return s.trim().split("\\|");
}
//对返回字符串数组进行检验
public static boolean checkArray(String[] s){
if(s.length!=5) return false;
return true;
}
public static boolean checkArrayAll(String[] s,int rows,String data){
boolean flag=true;
for(int i=0;i<=4;i++)
s[i]=s[i].trim(); //去除多余空格
String test=s[0];
//检查日期时间合法
/*
格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],
“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),
“时”为一位数时之前不加“0”,
“分”始终保持两位,“秒”始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
*/
//时间正则
String time="(?:(?:( [1-9]| 1[0-9]| 2[0-3]| 00):00))";
//日期正则,空格也会有影响,注意空格
// /所有年份 /1-12都有1-28 /1,3,5,7,8,10,12都有1-31天 /除2月外 都有29-30天
String regex1="(?:((?:([1-9]([0-9]{0,3}))/((?:(([1-9]|(1[0-2]))/(?:([1-9]|([1-2][0-8])|19))))|(?:(([13578])|([1][02])(/31)))|(?:(([13-9]|1[02])/(29|30)))))(?:(?:( [02468]| 1[02468]| 2[02]|):00))))";
//1或2位闰年 /3,4位闰年 //400年一润,百年不润
String regex2="(?:((?:([48]|[2468][048]|[13579][26]))|((?:(([1-9]([0-9]?))?:(0[48]|[2468][048]|[13579][26])))|(?:([48]|[2468][048]|[13579][26])00))/2/29)(?:(?:( [02468]| 1[02468]| 2[02]|):00)))";
String regexend=regex1+"|"+regex2;
if(!test.matches(regexend)) {System.out.printf("Row:%d,Column:%dWrong Format\n",rows,1);flag=false;}
//检查水位数据合法
test=s[1];
//水位数据正则 目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
String water ="(?:(?:(([1-9]([0-9]{0,2})))(?:((.[0-9]{1,3})?))))";
if(!test.matches(water)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,2);flag=false;}
test=s[2];
if(!test.matches(water)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,3);flag=false;}
//检查开度
test=s[3];
int id=test.indexOf("/");
String test1=test.substring(0,id); //目标开度
String test2=test.substring(id+1,test.length());//实际开度
String hot="(?:(([1-9])(?:(.[0-9]{2}))))";
if(!test1.matches(hot)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,4);flag=false;}
if(!test2.matches(hot)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,5);flag=false;}
//检查流量合法
test=s[4];
if(!test.matches(water)){System.out.printf("Row:%d,Column:%dWrong Format\n",rows,6);flag=false;}
//如果开度输入合法但大小不合法
double target=Double.valueOf(test1);
double actual=Double.valueOf(test2);
if(flag)
if (actual > target) System.out.printf("Row:%d GateOpening Warning\n",rows);
//如果存在不合法的数据,打印一次该数据未处理前的原数据
if(flag==false) System.out.println("Data:"+data);
if(flag==false) mark=1;
return flag;
}
}
class waterDate{
String time;
String targerLevel;//目标水位
String actualLevel;//实际水位
String targerOpenness;//目标开度
String actualOpenness;//实际开度
}
输出结果如下:

分析:设计思路有以下几点:
主方法中进行数据输入,接收输入数据采用StringBuilder;
数据校检设计为CheckDate类;
数据处理(计算等)设计为Deal Date类;
分水口门的调水信息设计为HydrologicalIfo ;
测量时间属性类使用LocalDateTime;
对字符串进行分割处理;
对应字符串各部分进行合法判断。
类结构如下:

题目集4(7-2):日期面向对象设计(聚合一)

代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;
int choice = input.nextInt();
if (choice == 1) { // test getNextNDays method
int m = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
m = input.nextInt();
if (m < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
n = input.nextInt();
if (n < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(
date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next());
DateUtil fromDate = new DateUtil(year, month, day);
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class DateUtil {
private int year;
private int month;
private int day;
public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public DateUtil(){}
public void setYear(int year) {
this.year = year;
}
public void setMonth(int month) {
this.month = month;
}
public void setDay(int day) {
this.day = day;
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
private final int[] DAY_OF_MONTH = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private int getDayOfMonth(int year, int month) {
int days = DAY_OF_MONTH[month - 1];
if (month == 2 && isLeapYear(year)) {
days = 29;
}
return days;
}
public boolean checkInputValidity()//检测输入的年、月、日是否合法
{
if (year < 1820 || year > 2020) return false;
if (month < 1 || month > 12) return false;
// int _day = this.getDayOfMonth(year, month);
// return day <= _day;
return day >= 1 && day <= 31;
}
public boolean isLeapYear(int year)//判断year是否为闰年
{
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
public DateUtil getNextNDays(int n)//取得year-month-day的下n天日期
{
int year = this.year;
int month = this.month;
int day = this.day;
// day = Math.min(day, this.getDayOfMonth(year, month));
for (int i = 0; i < n; i++) {
day++;
if (day > getDayOfMonth(year, month)) {
day = 1;
month++;
if (month > 12) {
month = 1;
year++;
}
}
}
return new DateUtil(year, month, day);
}
public DateUtil getPreviousNDays(int n)//取得year-month-day的前n天日期
{
int year = this.year;
int month = this.month;
int day = this.day;
for (int i = 0; i < n; i++) {
day--;
while (day < 1) {
month--;
if (month < 1) {
month = 12;
year--;
}
day += getDayOfMonth(year, month);
}
}
return new DateUtil(year, month, day);
}
public boolean compareDates(DateUtil date)//比较当前日期与date的大小(先后)
{
if (this.year > date.year) return true;
if (this.year == date.year) {
if (this.month > date.month) return true;
if (this.month == date.month) {
if (this.day >= date.day) return true;
}
}
return false;
}
public boolean equalTwoDates(DateUtil date)//判断两个日期是否相等
{
if (date != null) {
if (year == date.year && month == date.month && day == date.day) {
return true;
}
}
return false;
}
private static final int[] mon = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
public int getDaysofDates(DateUtil date)//求当前日期与date之间相差的天数
{
DateUtil dateUtil1 = this; // 小
DateUtil dateUtil2 = date; // 大
if (this.compareDates(date)) {
dateUtil1 = date;
dateUtil2 = this;
}
int days;
int leapYearNum = 0;
for (int i = dateUtil1.getYear(); i < dateUtil2.getYear(); i++) {
if (isLeapYear(i)) {
leapYearNum++;
}
}
days = 365 * (dateUtil2.getYear() - dateUtil1.getYear()) + leapYearNum;
int d1 = mon[dateUtil1.getMonth() - 1] + dateUtil1.getDay() + (dateUtil1.getMonth() > 2 && isLeapYear(dateUtil1.getYear()) ? 1 : 0);
int d2 = mon[dateUtil2.getMonth() - 1] + dateUtil2.getDay() + (dateUtil2.getMonth() > 2 && isLeapYear(dateUtil2.getYear()) ? 1 : 0);
return days - d1 + d2;
}
public String showDate()//以“year-month-day”格式返回日期值
{
return year + "-" + month + "-" + day;
}
}
分析:
类结构如下:
思路:构建Main类,DateUtil类,Day类,Month类,Year类。DateUtil与 Day类、Day类与Month类、Month与Year类聚合;
输出结果如下:
样例1:

样例2
样例3:

样例4:
题目集5(7-5)日期问题面向对象设计(聚合二):

代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;
int choice = input.nextInt();
if (choice == 1) { // test getNextNDays method
int m = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
m = input.nextInt();
if (m < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
n = input.nextInt();
if (n < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(
date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next());
DateUtil fromDate = new DateUtil(year, month, day);
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class DateUtil {
private int year;
private int month;
private int day;
public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public DateUtil(){}
public void setYear(int year) {
this.year = year;
}
public void setMonth(int month) {
this.month = month;
}
public void setDay(int day) {
this.day = day;
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
private final int[] DAY_OF_MONTH = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private int getDayOfMonth(int year, int month) {
int days = DAY_OF_MONTH[month - 1];
if (month == 2 && isLeapYear(year)) {
days = 29;
}
return days;
}
public boolean checkInputValidity()//检测输入的年、月、日是否合法
{
if (year < 1820 || year > 2020) return false;
if (month < 1 || month > 12) return false;
// int _day = this.getDayOfMonth(year, month);
// return day <= _day;
return day >= 1 && day <= 31;
}
public boolean isLeapYear(int year)//判断year是否为闰年
{
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
public DateUtil getNextNDays(int n)//取得year-month-day的下n天日期
{
int year = this.year;
int month = this.month;
int day = this.day;
// day = Math.min(day, this.getDayOfMonth(year, month));
for (int i = 0; i < n; i++) {
day++;
if (day > getDayOfMonth(year, month)) {
day = 1;
month++;
if (month > 12) {
month = 1;
year++;
}
}
}
return new DateUtil(year, month, day);
}
public DateUtil getPreviousNDays(int n)//取得year-month-day的前n天日期
{
int year = this.year;
int month = this.month;
int day = this.day;
for (int i = 0; i < n; i++) {
day--;
while (day < 1) {
month--;
if (month < 1) {
month = 12;
year--;
}
day += getDayOfMonth(year, month);
}
}
return new DateUtil(year, month, day);
}
public boolean compareDates(DateUtil date)//比较当前日期与date的大小(先后)
{
if (this.year > date.year) return true;
if (this.year == date.year) {
if (this.month > date.month) return true;
if (this.month == date.month) {
if (this.day >= date.day) return true;
}
}
return false;
}
public boolean equalTwoDates(DateUtil date)//判断两个日期是否相等
{
if (date != null) {
if (year == date.year && month == date.month && day == date.day) {
return true;
}
}
return false;
}
private static final int[] mon = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
public int getDaysofDates(DateUtil date)//求当前日期与date之间相差的天数
{
DateUtil dateUtil1 = this; // 小
DateUtil dateUtil2 = date; // 大
if (this.compareDates(date)) {
dateUtil1 = date;
dateUtil2 = this;
}
int days;
int leapYearNum = 0;
for (int i = dateUtil1.getYear(); i < dateUtil2.getYear(); i++) {
if (isLeapYear(i)) {
leapYearNum++;
}
}
days = 365 * (dateUtil2.getYear() - dateUtil1.getYear()) + leapYearNum;
int d1 = mon[dateUtil1.getMonth() - 1] + dateUtil1.getDay() + (dateUtil1.getMonth() > 2 && isLeapYear(dateUtil1.getYear()) ? 1 : 0);
int d2 = mon[dateUtil2.getMonth() - 1] + dateUtil2.getDay() + (dateUtil2.getMonth() > 2 && isLeapYear(dateUtil2.getYear()) ? 1 : 0);
return days - d1 + d2;
}
public String showDate()//以“year-month-day”格式返回日期值
{
return year + "-" + month + "-" + day;
}
}
分析:
类结构图如下:

思路:构建Main类、DateUtil类、Year类、Month类、Day类。DateUtil类分别与Year类、Month类、Day类聚合。
输出结果如下:
样例1:

样例2:

样例3:

样例4:
题目集4(7-3):

代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int flag = input.nextInt();
if(flag == 1) {
double radius = input.nextDouble();
if (radius <= 0){
System.out.println("Wrong Format");
System.exit(0);//输入错误,直接结束;
}
Circle circle = new Circle();
circle.setRadius(radius);
System.out.printf("Circle's area:%.2f\n", circle.getArea());
}
else if(flag == 2) {
double length = input.nextDouble();
double width = input.nextDouble();
if (length <= 0 || width <= 0){
System.out.println("Wrong Format");
System.exit(0);
}
Rectangle rectangle = new Rectangle();
rectangle.setLength(length);
rectangle.setWidth(width);
System.out.printf("Rectangle's area:%.2f\n", rectangle.getArea());
}
else if(flag == 3){
double radius = input.nextDouble();
if (radius <= 0){
System.out.println("Wrong Format");
System.exit(1);
}
Ball ball = new Ball();
ball.setRadius(radius);
System.out.printf("Ball's surface area:%.2f\n", ball.getArea());
System.out.printf("Ball's volume:%.2f\n", ball.getVolume());
}
else if(flag == 4){
double length = input.nextDouble();
double width = input.nextDouble();
double height = input.nextDouble();
if (length <= 0 || width <= 0 || height <= 0){
System.out.println("Wrong Format");
System.exit(0);
}
Box box = new Box();
box.setLength(length);
box.setWidth(width);
box.setHeight(height);
System.out.printf("Box's surface area:%.2f\n", box.getArea());
System.out.printf("Box's volume:%.2f\n", box.getVolume());
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class Shape{
public Shape(){
System.out.println("Constructing Shape");
}
public double getArea(){
return 0.0;
}
}
class Circle extends Shape{
private double radius;
public Circle(){
System.out.println("Constructing Circle");
}
public double getRadius(){
return radius;
}
public void setRadius(double radius){
this.radius = radius;
}
@Override
public double getArea(){
return radius * radius * Math.PI;
}
}
class Rectangle extends Shape{
private double width;
private double length;
public Rectangle(){
System.out.println("Constructing Rectangle");
}
public double getWidth(){
return width;
}
public void setWidth(double width){
this.width = width;
}
public double getLength(){
return length;
}
public void setLength(double length){
this.length = length;
}
@Override
public double getArea(){
return width * length;
}
}
class Ball extends Circle{
public Ball(){
System.out.println("Constructing Ball");
}
//求球表面积
@Override
public double getArea(){
return 4 * super.getRadius() * super.getRadius() * Math.PI;
}
//求球体积
public double getVolume(){
return 4.0 / 3.0 * Math.PI * Math.pow(super.getRadius(), 3);
}
}
class Box extends Rectangle{
private double height;
public Box(){
System.out.println("Constructing Box");
}
public double getHeight(){
return height;
}
public void setHeight(double height){
this.height = height;
}
//立方体表面积
@Override
public double getArea(){
return (super.getArea() + height * super.getWidth() + height * super.getLength()) * 2;
}
//立方体表面积
public double getVolume(){
return height * super.getArea();
}
}
分析:主方法内,主要实现四个功能(1-4): 从键盘输入1,则定义圆类,从键盘输入圆的半径后,主要输出圆的面积; 从键盘输入2,则定义矩形类,从键盘输入矩形的宽和长后,主要输出矩形的面积; 从键盘输入3,则定义球类,从键盘输入球的半径后,主要输出球的表面积和体积; 从键盘输入4,则定义立方体类,从键盘输入立方体的宽、长和高度后,主要输出立方体的表面积和体积;
假如数据输入非法(包括圆、矩形、球及立方体对象的属性不大于0和输入选择值非1-4),系统输出Wrong Format.
输出结果如下:
样例1:

样例2:

样例3:

题目集6(7-5):

代码如下:


分析:
从键盘首先输入三个整型值(例如a b c),分别代表想要创建的Circle、Rectangle及Triangle对象的数量,然后根据图形数量继续输入各对象的属性值(均为实型数),数与数之间可以用一个或多个空格或回车分隔。
如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边关系),则输出Wrong Format。
如果输入合法,则正常输出,输出内容如下(输出格式见输入输出示例):
各个图形的面积;
所有图形的面积总和;
排序后的各个图形面积;
再次所有图形的面积总和。
Array List应用:要创建的各个图形对象均存储在ArrayList<Shape>类型的列表中,用到 方法如下:add()、toArray()。
类结构如下:

输出结果如下:
样例1:

样例2:

样例3:

题目集6(7-6):实现图形接口及多态性

代码如下:
import java.util.Scanner;
import java.util.Arrays;
//GetArea类
interface GetArea{
public double Mj();
}
//Circle类
class Circle implements GetArea{
private double r;
//创建无参构造方法
public Circle(){
}
//创建带参构造方法
public Circle(double r){
this.r=r;
}
//getter
public double getR(){
return r;
}
//setter
public void setR(double r){
this.r = r;
}
//计算圆面积
public double Mj(){
return Math.PI*r*r;
}
}
//Rectangle类
class Rectangle implements GetArea{
private double a,b;
//创建无参构造方法
public Rectangle(){
}
//创建带参构造方法
public Rectangle(double a, double b){
this.a=a;
this.b=b;
}
//getter
public double A(){
return a;
}
public double B(){
return b;
}
//setter
public void setA(double a){
this.a=a;
}
public void setB(double b){
this.b=b;
}
//计算矩形面积
public double Mj(){
return a*b;
}
}
//主类
public class Main{
public static void main(String[] args){
Scanner x = new Scanner(System.in);
double ybj,jxc,jxk;
double yl,kp;
ybj=x.nextDouble();
jxc=x.nextDouble();
jxk=x.nextDouble();
if(ybj<=0||jxc<=0||jxk<=0){//如果不合法
System.out.println("Wrong Format");
System.exit(0);
}
GetArea yuanmianji=new Circle(ybj);
GetArea juxingmianji=new Rectangle(jxc,jxk);
yl=yuanmianji.Mj();
kp=juxingmianji.Mj();
System.out.printf("%.2f\n",yl);
System.out.printf("%.2f\n",kp);
}
}
分析:如果输入的圆的半径值及矩形的宽、长的值非法(≤0),则输出Wrong Format
如果输入合法,则分别输出圆的面积和矩形的面积值(各占一行),保留两位小数。必须实现类的封装性、继承性和多态性。
类结构如下:

输出结果如下:
样例1:

样例2:

题目集5(7-4):统计Java程序中关键词的出现次数。

代码如下:
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Scanner x = new Scanner(System.in);
StringBuilder a = new StringBuilder();
Map map=new TreeMap();
String[] gjc = {"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while"};
String kg,exit="exit";
int i,n,flag=0;
//输入
kg = x.nextLine();
while( !kg.equals(exit)) {
a.append(kg.replaceAll("//.*", " ").replaceAll("\".*\"", " "));//去掉"//"后和的内容以及双引号里的内容
kg = x.nextLine();
flag=1;
}
String b = a.toString().replaceAll("/\\*\\s*.*\\s*\\*/", " ");//去掉"/* */"里的内容,放入字符串b中
//System.out.println(b);
//如果没有内容
if(flag==0) {
System.out.println("Wrong Format");
}
// 循环找每个关键词出现的次数
for(i=0;i< gjc.length;i++) {
Pattern pattern = Pattern.compile("\\b"+gjc[i]+"\\b");//创建关键词的正则表达式
Matcher matcher = pattern.matcher(b);//字符串与关键词匹配
n=0;
while(matcher.find()) {//找到该关键词的话,记录该关键词的次数
n++;
//System.out.println(matcher.group());
}
if(n!=0){//把次数不是0的关键词替换为次数
map.put(gjc[i], n);
}
//System.out.println(map);
}
//System.out.println(map);
String map1= String.valueOf(map);//把map转化为字符串map1
//System.out.println(map1);
String map2=map1.replace("{","").replace("}","");//把map1里的"{""}"去掉存入字符串map2
//System.out.println(map2);
String[] map3=map2.split(", ");//把map2根据", "分开,存入字符串数组map3
//循环输出
for (i=0;i< map3.length;i++){
String[] map4=map3[i].split("=");//把每个字符串map3根据"="分开,存入字符串数组map4
System.out.println(map4[1]+"\t"+map4[0]);
}
}
}
分析:当未输入源码时,程序输出Wrong Format
当没有统计数据时,输出为空
当有统计数据时,关键字按照升序排列,每行输出一个关键字及数量,格式为数量\t关键字
输出结果如下:

①题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较。
7-4使用与7-2不同的是使用DateUtil类分别与Day、Month、Year类聚合。聚合的类使两个类处于同一层次,更好的实现了代码的复用。
②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)。
(1)参考题目集 4 中 7-3 中图形类的继承层次结构,题目集6(7-5、7-6)作业重点研究平面图形相关的处理方法。getArea()方法为抽象方法,功能为求得图形的面积;validate()方法也为抽象方法,对图形的属 性进行合法性校验;toString()继承自 Object,功能为输出图形的面积信息,其格式参考输出示例。 (2)多态的应用 学习 Java 语言的过程中,对于多态的理解是非常关键的,理解了多态也就意味着打开了理解 Java 各种“抽象”的大门。 所谓的“多态”,简单的理解就是对象在不同情况下的不同表现,具体体现在定义和功能两个方 面,简单的总结一下,多态可以用“三个定义和两个方法”来总结。三个定义分别是父类定义子类构 建、接口定义实现类构建和抽象类定义实体类构建,而两个方法分别是方法重载和方法重写。本次作 业我们采用的是抽象类定义、实体类构建的方式。即 Shape 为抽象类,Circle、Rectangle 及 Triangle 为实体类。
③对三次题目集中用到的正则表达式技术的分析总结
题目集中使用了正则表达式的以下功能:匹配验证、查找和替换、字符串分割与子符截取。
④题目集5(7-4)中Java集合框架应用的分析总结。
所有集合类都位于java.util包下。集合中只能保存对象(保存对象的引用变量)。(数组既可以保存基本类型的数据也可以保存对象)。当我们把一个对象放入集合中后,系统会把所有集合元素都当成Object类的实例进行处理。从JDK1.5以后,这种状态得到了改进:可以使用泛型来限制集合里元素的类型,并让集合记住所有集合元素的类型(参见具体泛型的内容)。
三 、踩坑心得
1、未区分清楚隐藏与重写。
本质上面的区别在于:隐藏是静态绑定,按照编译时引用的静态类型和决定调用的,重写是动态绑定的,是按照运行时引用所指向对象的实际类型决定调用相关类型。从另一个方面来讲假如子类隐藏了父类,则通过父类引用调用的仍旧是父类的方法;另一方面子类要是重写了父类的方法,则父类引用指向子类对象时候,通过父类的引用调用的是子类方法。
2、Java接口中的误区。
接口是按照抽象设计的,无法实例化。让A用new方式创建的借口类型,事实上是创建了一个匿名类型,这个匿名可以实现接口类型。
四 、改进建议
(1)在以后的代码中时刻记得面向对象的三大特性,并加以应用:
1、封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
2、继承
提高代码复用性;继承是多态的前提。
3、多态
父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。。
(2)、待经过更多学习继续发现代码不足再来补充.
五 、总结。
(1)通过本阶段三次题目集的综合性总结,学习了Java面向对象的封装性、继承性、多态性,以及类与类之间的聚合关系。
(2)学习了Java面向对象的单一对象原则,以及面对对象的好处.。
(3)需要进一步学习面向对象更多原则,并熟练掌握正则表达式。
多了解UML的设计,注意代码的复杂度的,提升代码的质量.
(4)在老师的优秀的线上线下教学系统下,需要更加认真的学习,提升自身能力.




浙公网安备 33010602011771号