Java第一次随笔
作者:互联网
经过两个月对于Java语言的学习,我认为有必要总结一下学习成果。下面是我近期学习的内容和对题目集的理解,以及对测试点的踩坑心得。
在学习Java语言的初期,在我看来Java语言的基本语法和C语言差不多,Java语言和C语言在很多方面的语法很相似,比如说循环语句,条件语句等。但是Java语言和C语言也有着不一样的地方,比如说在输入和输出是,c的输入方法是调用scanf()在括号中输入内容完成对变量的赋值,c的输出方法是调用printf(),在括号里面输入%d,%f,%c,%s等来输出整数型数字,浮点数,字符以及字符串等。尤其要注意的是,c在输入和输出的过程中要特别在逗号后面声明变量的地址,否则语法上不通过。在Java语言中您可以简单地使用System.out.println(); 或System.out.print(); 或System.out.print()将输出发送到标准输出(屏幕)。
示例:
class Main {
public static void main(String[] args) {
System.out.println("Java programming is interesting.");
}
}
关于println(),print()和printf()之间的区别
print() - 它在引号内打印字符串。
println() - 它在引号内打印字符串,类似于print()方法,相当于在print() 方法中加入了一个换行符。
printf() -格式化输出括号中的内容,于C中的printf()方法相似。
Java中的输入方法和C有很大的区别,首先Java语言输入之前要先加入一个包,import java.util.Scanner;来使我们可以创建Scanner对象,
Scanner input=new Scanner(System.in);
在创建完对象之后我们可以进行输入。
Int a=input.nextInt();
double a=input.nextDouble();
示例:
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println(“请输入一个整数”)
int x=input.nextInt();
System.out.println(“您输入的整数为”+x);
}
}
需要注意的是在输入不同类型的数据时要采用不同的输入类型,输入浮点数是采用input.nextFloat或者input.nextDouble。输入字符类型时可以用Input.next()或者Input.nextLine()。
在学习面向对象的过程中,对象的创建对我认知的冲击比较大,我们在创建对象的时候要考虑的两个方面:对象的属性和方法。这样说比较晦涩难懂,我举一个简单的例子,假如我们现在要创建一个“学生”的类,那么这个学生类里面应该要包括这个学生的学号,姓名等,这些称之为属性。学生要运动,要吃饭,要回答问题,这些学生的行为我们称之为方法。也就是说在对象中对象的基本信息就是属性,对象的行为称之为方法。
我们知道Java语言是面向对象的程序设计,其包括了三大基本要素:封装,继承以及多态。下面我来简单介绍一下这三个特征。
首先关于封装性,我们都知道在c语言中有一个神奇的东西叫做指针,它里面承载了内存地址,我们可以通过指针来便捷的访问和更改某一处数据,但是这就存在了一定的安全隐患。我们可以想一下,如果任何人都可以随意的更改数据,那么这个程序一定是不安全的。于是在Java语言设计时就有了这么一种性质,封装性。
在面向对象程序设计的过程中,我们要创建对象,在对象内部我们引用关键词private来对属性进行封装,private的意思是私有的,也就是说在对象外部,我们并不能直接访问这个属性,而是要通过对象内部的方法来进行访问或是更改。
例如:
class Year{
private int y;
public Year(int y) {
this.y = y;
}
public Year() {
}
public int getY() {
return y;
}
}
我们用年份举例,上面我们有一个类表示年。在这个类之中我们的y属性是私有的,于是在对象外部我们就不能直接访问这个属性,而是要通过get和set方法来进行访问或更改。
其次关于继承,继承的关键词为extends。其中包括子类和父类。子类又可以称为派生类。父类又可以称为超类(Super Class),要注意的是在Java语言中只能实现单继承,就是说一个类只能有一个父类。
我们举一个继承的例子:
class Person{//父类
private String name;
private int age;
public void setName(String name){
this.name=name;
}
public void setAge(int age){
this.age=age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
}
class Student extends Person{ //Student类继承了Person类
private String school; //子类扩充属性
//子类扩充方法
public void setSchool(String school){
this.school=school;
}
public String getSchool(){
return this.school;
}
}
在上面的例子中我们有一个Person类,Student类继承了Person类,同时也代表这Student类继承了Person类中public方法(注意私有的属性是无法继承的)。
要注意的是当子类方法和父类方法名字一样时,子类中的方法会覆盖父类中的方法,称之为方法的重载。
最后关于多态,多态中涉及到的几个概念,向上转型和向下转型,向上转型。是子类型转到父类型,向下转型是父类型转到子类型,无论是向上转型还是向下转型,两种类型之间必须有继承关系,否则编译器无法通过。下面举个动物类的例子
Class Animal{
Public void move(){
System.out.print(“动物在移动”)
}
}
Class Cat extend Animal {
Public void move(){
System.out.print(“猫在走猫步”)
}
}
Class Bird extend Animal {
Public void move(){
System.out.print(“鸟在飞”)
}
}
以下语句是正确的
Animal a = new Cat();
只是一个向上转型的例子,Animal和Cat存在继承关系。 Java中存在这样的语法,父类型的引用指向子类型的对象。
1. Java程序永远都分为编译阶段和运行阶段。
2.先分析编译阶段,再分析运行阶段,编译阶段无法通过,则程序无法运行。
3.编译阶段编译器检查a这个引用的数据类型为Animal,由于animal class中move 这个方法,所以编译通过了。这个过程我们称之为静态绑定或者编译阶段绑定,只有静态绑定成功之后才有后续的运行。
4.在程序运行阶段。JVA对于内存当中真实创建的对象是cat对象。那么程序运行阶段一定会调用cat对象里的move方法。此时发生了程序的动态绑定即运行阶段绑定。
5.父类型引用指向子类型应用这种机制导致的程序。存在编译阶段和运行阶段两种不同的形态或状态。这种机制可以称为一种多态机制。
以上是前端时间对知识点的简单概阔,下面分析在习题中所遇到的问题
这是一个关于日期计算的问题
1.参考题目集二中和日期相关的程序,设计一个类DateUtil,该类有三个私有属性year、month、day(均为整型数),其中,year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 除了创建该类的构造方法、属性的getter及setter方法外,需要编写如下方法:
public boolean checkInputValidity();//检测输入的年、月、日是否合法
public boolean isLeapYear(int year);//判断year是否为闰年
public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期
public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期
public boolean compareDates(DateUtil date);//比较当前日期与date的大小(先后)
public boolean equalTwoDates(DateUtil date);//判断两个日期是否相等
public int getDaysofDates(DateUtil date);//求当前日期与date之间相差的天数
public String showDate();//以“year-month-day”格式返回日期值
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
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,month,day;
int []a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
public DateUtil(DateUtil d){
this.day = d.getDay();
this.month = d.getMonth();
this.year = d.getYear();
}
public DateUtil(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
public void setDay(int day) {
this.day = day;
}
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
public int getYear() {
return year;
}
public void setMonth(int month) {
this.month = month;
}
public void setYear(int year) {
this.year = year;
}
public boolean checkInputValidity() {
int[] a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year)){
a[2]=29;
}
if(year>=1820&&year<=2020&&month>0&&month<=12&&day<=a[month]&&day>0){
return true;
}
else
return false;
}
public boolean isLeapYear(int year){
if(( year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){
return true;
}
else
return false;
}
public DateUtil getNextNDays(int n){
DateUtil newdate = new DateUtil(this);
int[] a = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
int years=0;
if(!isLeapYear(newdate.year)&&isLeapYear(newdate.year+1)&&newdate.getMonth()>2){
n=n-366;
}
while(n>years){
if(isLeapYear(newdate.year))
years=366;
else
years=365;
newdate.year++;
n=n-years;
}
for (int i = 1; i <= n; i++) {
newdate.day++;
if(isLeapYear(newdate.year)) {
a[2] = 29;
}
else {
a[2] = 28;
}
if (newdate.day > a[newdate.month]) {
newdate.day = 1;
newdate.month++;
if (newdate.month > 12) {
newdate.month = 1;
newdate.year++;
}
}
}
return newdate;
}
public DateUtil getPreviousNDays(int n){
DateUtil newdata = new DateUtil(this);
while (n>=365) {
if(isLeapYear(newdata.year)) {
newdata.year = newdata.year - 1;
n = n - 366;
}
if(!isLeapYear(newdata.year)) {
newdata.year = newdata.year - 1;
n = n - 365;
}
}
for(int i = 0; i < n; i++){
newdata.setDay(newdata.getDay() - 1);
if(newdata.getDay() <= 0){
newdata.setMonth(newdata.getMonth() - 1);
if(newdata.getMonth() <= 0){
newdata.setMonth(12);
newdata.setYear(newdata.getYear() - 1);
}
if(isLeapYear(newdata.getYear()) && newdata.getMonth() == 2)
newdata.setDay(29);
else
newdata.setDay(newdata.a[newdata.getMonth()]);
}
}
return newdata;
}
public boolean compareDates(DateUtil date){
if(year > date.getYear())
return true;
else if(year == date.getYear() && month > date.getMonth())
return true;
else if(year == date.getYear() && month == date.getMonth() && day > date.getDay())
return true;
return false;
}
public boolean equalTwoDates(DateUtil date){
if(this.year != date.getYear())
return false;
else if(this.day != date.getDay())
return false;
else if(this.month != date.getMonth())
return false;
else
return true;
}
public int getDaysofDates(DateUtil date){
int x = 0;
DateUtil newdata = new DateUtil(this);
if(this.compareDates(date)){
while(newdata.getYear() - date.getYear() >= 2){
if(newdata.isLeapYear(newdata.getYear()) && newdata.getMonth() > 2)
x = x + 366;
else if(newdata.isLeapYear(newdata.getYear() - 1) && newdata.getMonth() <= 2)
x = x + 366;
else
x = x + 365;
newdata.setYear(newdata.getYear() - 1);
}
while(true){
if(newdata.equalTwoDates(date))
break;
x++;
newdata.setDay(newdata.getDay() - 1);
if(newdata.getDay() <= 0){
newdata.setMonth(newdata.getMonth() - 1);
if(newdata.getMonth() <= 0){
newdata.setMonth(12);
newdata.setYear(newdata.getYear() - 1);
}
if(isLeapYear(newdata.getYear()) && newdata.getMonth() == 2)
newdata.setDay(29);
else
newdata.setDay(newdata.a[newdata.getMonth()]);
}
}
}
else{
while(date.getYear() - newdata.getYear() >= 2){
if(newdata.isLeapYear(newdata.getYear()) && newdata.getMonth() <= 2)
x = x + 366;
else if(newdata.isLeapYear(newdata.getYear() + 1) && newdata.getMonth() > 2)
x = x + 366;
else
x = x + 365;
newdata.setYear(newdata.getYear() + 1);
}
while(true){
if(newdata.equalTwoDates(date))
break;
x++;
newdata.setDay(newdata.getDay() + 1);
if(isLeapYear(newdata.getYear()) && newdata.getMonth() == 2){
if(newdata.getDay() > 29){
newdata.setMonth(newdata.getMonth() + 1);
newdata.setDay(1);
}
}
else if(newdata.getDay() > newdata.a[newdata.getMonth()]){
newdata.setMonth(newdata.getMonth() + 1);
newdata.setDay(1);
if(newdata.getMonth() > 12){
newdata.setMonth(1);
newdata.setYear(newdata.getYear() + 1);
}
}
}
}
return x;
}
public String showDate(){
return year + "-" + month + "-" + day;
}
}
这是此题的源代码。
在写这道题的时候,我认为在计算日期前n天和后n天的时候很伤脑筋,在最开始我的思路是如果n大于365,就先一年一年的算,遇到润年就减去366,否则就减去365.但是在测试的时候遇到了一个问题。在测试这一组数据的时候1 1999 3 28 6543,输出结果应该是2017-2-24。最开始我的输出结果一直是2017-2-25,随后我注意到了一个问题,1999年是一个平年,但是2000年是一个闰年,而且我们是从1999年的3月28日开始算的,到了2000年的3月28日,我经历了366天而不是365天,这就是为什么结果比正确答案多算了一天。于是我们多加一种情况:如果今年是平年,但是下一年是闰年,而且我们是从今年的3月之后开始算的,那我们就应该减去366而不是365.
2.我们换一种想法,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
类的代码如下:
class Year{
int value;
public Year(){
}
public Year(int value){
this.value=value;
}
public int getValue(){
return value;
}
public void setValue(int value){
this.value=value;
}
public boolean isLeapYear(int value){
if((value%4==0&&value%100!=0)||value%400==0)
return true;
else
return false;
}
public boolean isLeapYear(){
if((value%4==0&&value%100!=0)||value%400==0)
return true;
else
return false;
}
public boolean validate(){
if(value<=2050&&value>=1900)
return true;
else
return false;
}
public void yearIncrement(){
value=value+1;
}
public void yearReduction(){
value=value-1;
}
}
class Month{
int value;
Year year;
public Month(){
}
public Month(int yearValue,int monthValue){
this.year=new Year(yearValue);
this.value=monthValue;
}
public int getValue(){
return value;
}
public Year getYear(){
return year;
}
public void setValue(int value){
this.value=value;
}
public void setYear(Year year){
this.year=year;
}
public void resetMin(){
value=1;
}
public void resetMax(){
value=12;
}
public boolean validate(){
if(value>=1&&value<=12)
return true;
else
return false;
}
public void monthIncrement(){
value=value+1;
}
public void monthReduction(){
value=value-1;
}
}
//Day类
class Day{
int value;
Month month;
int a[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
public Day(){
}
public Day(int yearValue,int monthValue,int dayValue){
this.month=new Month(yearValue,monthValue);
this.value=dayValue;
}
public int getValue(){
return value;
}
public Month getMonth(){
return month;
}
public void setValue(int value){
this.value=value;
}
public void setMonth(Month value){
this.month=value;
}
public void resetMin(){
value=1;
}
public void resetMax(){
value=a[month.getValue()-1];
}
public boolean validate(){
if(this.getMonth().getYear().isLeapYear())
a[1]=29;
if(value>=1&&value<=a[month.getValue()])
return true;
else
return false;
}
public void dayIncrement() {
value=value+1;
}
public void dayReduction() {
value=value-1;
}
}
我们将DateUtil类和Day类关联在一起Day类和Month类关联在一起,Month类和Year类关联在一起。这样我们知道了day就可以知道这一天的年份和月份。这是一个链式结构,彼此之间的耦合性很强,对于程序设计而言不够简洁,下面还有另外一种聚合。
3.类图如下:
在这个聚合之中,我们将年月日分开表示,这样做的好处是可以便捷的访问年月日,而不是像上次的聚合那样,必须要通过day才能访问其他属性,这次的聚合显然更加方便。类的代码如下:
class Year{
private int y;
public Year(int y) {
this.y = y;
}
public Year() {
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void yearIncrement(){
this.y++;
}
public void yearReduction(){
this.y--;
}
}
class Month{
private int m;
public Month(int m) {
this.m = m;
}
public Month() {
}
public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}
public void monthIncrement(){
this.m++;
}
public void monthReduction(){
this.m--;
}
public void resetMin(){
m=1;
}
public void resetMax(){
m=12;
}
}
class Day {
private int d;
public Day(int d) {
this.d = d;
}
public Day() {
}
public int getD() {
return d;
}
public void setD(int d) {
this.d = d;
}
public void dayIncrement() {
this.d++;
}
public void dayReduction() {
this.d--;
}
}
这样分类,使得类之间的耦合度变得非常低,更加符合面向对象设计的初衷。
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//int year = 0;
//int month = 0;
//int day = 0;
Year year=new Year(0);
Month month = new Month(0);
Day day = new Day(0);
int choice = input.nextInt();
if (choice == 1) { // test getNextNDays method
int m = 0;
year.setY(Integer.parseInt(input.next()));
month.setM(Integer.parseInt(input.next()));
day.setD(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().getY() + "-" + date.getMonth().getM() + "-" + date.getDay().getD() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year.setY(Integer.parseInt(input.next()));
month.setM(Integer.parseInt(input.next()));
day.setD(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().getY() + "-" + date.getMonth().getM() + "-" + date.getDay().getD() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year.setY(Integer.parseInt(input.next()));
month.setM(Integer.parseInt(input.next()));
day.setD(Integer.parseInt(input.next()));
Year anotherYear = new Year(Integer.parseInt(input.next()));
Month anotherMonth = new Month(Integer.parseInt(input.next()));
Day anotherDay = new Day(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);
}
}
}
在这个主函数中,我改变了输入方式,没有直接对int型的变量赋值,而是先创建对象再通过set函数对对象内部的属性进行赋值,这是利用了Java语言的封装性,在创建对象的时候采用构造方法传入三个对象比如DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);其他算法与题目一一样,只是要将所有的变量用引用的方式替换。
总结:在学习Java的语法时,Java的语法是类似c语言的,所以学习的比较轻松。唯一需要注意的是有几个不容易搞清楚的关键字的用法,public,protected,private,static,在学习Java的面向对象的编程语言的特性。比如继承,构造器,抽象类,接口,方法的多态,重载,覆盖,Java的异常处理机制。对于一个没有面向对象语言背景的人来说,我觉得这个过程需要花很长很长时间,因为学习Java之前没有C++的经验,只有C语言的经验,花了很长时间,才彻底把这些概念都搞清楚,把书上面的例子反复的揣摩,修改,尝试,把那几章内容反复的看过来,看过去,看了很多遍,才领悟了。在之后的学习中,我认为还是要巩固基础知识,只有基础知识学明白才能更好的学习Java语言。
标签:Java,int,System,第一次,newdata,year,date,随笔,public 来源: https://www.cnblogs.com/zhaoziyiblog/p/16123419.html