日历(默认构造器)
要求:
做一个日历,功能和电脑、手机上的日历一样,能显示每个月的天数,1至12月每个月的天数都能正确显示(包括闰年2月29天,平年2月28天)。然后每个月的每一号显示该天对应的星期数。
代码:
package com.softeem.lesson06.oop;
/**
* 创建一个方法,获取一个指定年份,月份当月的总天数
* @author admini
*
*/
public class MyCalendar {
//判断是否是闰年
public boolean isLeapYear(int year){
return (year % 4 == 0 && year % 100 != 0)|year % 400 == 0;
}
//判断每个月的天数
public int getDaysOfMonth(int y,int m) {
switch(m) {
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
//是闰年返回29,不是则返回28
return isLeapYear(y)?29:28;
default:
return 31;
}
}
/**
* 计算从1900年1月份到参数的年份月份上一个月的总天数
* @param y
* @param m
* @return
*/
public int getTotalDaysFrom1900(int y,int m) {
//局部变量使用前必须先初始化
int days = 0;;
//计算整年的总天数1900~(y-1)
for(int i = 1900;i < y;i++) {
//是闰年加366,否则加365
days += isLeapYear(i)?366:365;//days = days + 366/365
}
//计算从1-(m-1)月的总天数
for(int i = 1;i < m;i++) {
days += getDaysOfMonth(y, i);//days = days + 28/29/30/31
}
return days;
}
/**
* 打印日历
* @param args
*/
public void printCalendar(int y,int m) {
//获取打印日历之前需要预留的空格数
//通过1900年到(y-1)年的总天数除以7来判断预留数(1900年1月1日正好对应星期一)
int space = getTotalDaysFrom1900(y,m) % 7;
//获取目标月份的总天数
int days = getDaysOfMonth(y,m);
//用表格的方式呈现日历,更符合实际,也更美观
System.out.println("===========SOFTEEM【"+y+"]年【"+m+"】月================");
//天数的最上一排显示星期数
System.out.println("一\t二\t三\t四\t五\t六\t日");
System.out.println("===================================================");
int count = 0;
//打印日期,用“\t"留出该月份需要预留的空格数
for(int i = 0;i < space;i++) {
System.out.print("\t");
count++;
}
//打印日期
for(int i = 1;i <=days; i++) {
count++;
System.out.print(i +"\t");
//是否达到周天,达到周天则换一行
if(count == 7){
System.out.println();
//计数器归零,再在下一轮重新判断是否达到周天
count = 0;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//定义新对象
MyCalendar mc = new MyCalendar();
//判断2019是否是闰年
boolean b = mc.isLeapYear(2019);
//是闰年打印“是”,否则打印“不是"
System.out.println(b?"shi":"bushi");
//定义2020年2月的天数
int days = mc.getDaysOfMonth(2020, 2);
//打印得到的结果
System.out.println(days);
//从1900年1月1日到2020年11月前的总天数
days = mc.getTotalDaysFrom1900(2020,11);
System.out.println(days);
//打印2020年11月的日历,是日历编写的总程序,可以通过设置参数得到我们想要月份的日历
mc.printCalendar(2020,11);
}
}
运行结果:
日历(设计构造器)
与默认的日历的程序基本设计一致,只是这里通过自己设计构造器的参数来达到降低编码的复杂度的目的。通过构造器赋值给全局变量不用再设置多个参数和局部变量。
代码:
package com.softeem.lesson07.example;
public class MyCalendar {
int year;
int month;
//定义构造器的参数,通过构造器直接将参数的数值直接赋值给全局变量
public MyCalendar(int _year,int _month) {
year = _year;
month = _month;
}
/**
* 判断指定的年份是否是闰年
*
* @param year
* @return
*/
public boolean isLeapYear(int year) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
/**
* 根据提供的年份月份,返回当前月的总天数
*
* @param y
* @param m
* @return
*/
public int getDaysOfMonth(int y, int m) {
switch (m) {
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
return isLeapYear(y) ? 29 : 28;
default:
return 31;
}
}
/**
* 计算从1900年1月份到目标的年份月份上一个月的总天
*
* @param y
* @param m
* @return
*/
//不用定义该方法内的参数,方法内直接引入全局变量”month”和“year”
public int getTotalDaysFrom1900() {
// 局部变量使用前必须先初始化
int days = 0;
// 计算整年的总天数1900~(y-1)
for (int i = 1900; i < year; i++) {
days += isLeapYear(i) ? 366 : 365; // days = days + 366/365
}
// 计算从1-(m-1)月的总天数 1 2 3 4 5 .. 10
for (int i = 1; i < month; i++) {
days += getDaysOfMonth(year, i); // days = days + 28/29/30/31
}
return days;
}
/**
* 打印日历
*
* @param y
* @param m
*/
public void printCalendar() {
// 获取打印日历之前需要预留的空格数
int space = getTotalDaysFrom1900() % 7;
// 获取目标年份月份的总天数
int days = getDaysOfMonth(year, month);
System.out.println("============SOFTEEM万年历 【" + year + "】年【" + month + "】月=============");
System.out.println("一\t二\t三\t四\t五\t六\t日");
System.out.println("====================================================");
int count = 0;
//打印空格
for (int i = 0; i < space; i++) {
System.out.print("\t");
count++;
}
//打印日期
for (int i = 1; i <= days; i++) {
count++;
System.out.print(i + "\t");
//是否达到周天
if(count == 7) {
System.out.println();
//计数器归零
count = 0;
}
}
}
public static void main(String[] args) {
//只通过定义构造器的参数来实现功能,几乎不需要定义其他参数
MyCalendar mc = new MyCalendar(2019,11);
mc.printCalendar();
}
}
运行结果:
总结
设计构造器的日历和默认构造器的日历实现功能一样,代码长度相近,从日历这个例子看不出两种方法的优劣之分。每种方法都有自己独特的应用,我们能做的不是区分方法的好坏,从而一味推崇一种或者一类方法。而是面对不同的情况,不同的要求,用更方便的方法来实现要求的功能。没有强调好坏,只是我们通过该方法实现的功能bug更少,更清楚理解整体结构。
我目前能力有限,对该方面的认识可能比价浅显,只有不断的学习,才能掌握理解更多的方法,理解透彻后才能更加灵活的运用在实践中。