第一天
1. Java命名规范:关键字、变量、对象、方法、包等名字通常全部字母小写,如果是多个单词构成的话就首字母小写,后面单词首字母大写,比如String类中的toString;类名首字母大写;常量名全部大写。
2. 基本数据类型:
**1)数据类型分类:**Java分为基本类型和引用类型 。其中,基本类型有byte、short、int、long、float、double、char、boolean,它们的变量作为参数传递时只是复制了一份,所以不会改变,比如int a=4;传到addOne(int a)这个方法执行后a的值还是4。引用类型有数组、类和接口,当它们的变量当做值传递的时候就会改变,就像C语言里面传递指针那样。
2)基本数据类型的取值范围以及字节数:
我觉得这个写得很好:Java 基本数据类型取值范围讲解
注意一个:boolean的默认值是false。
3)数组:
- 数组的声明:
int a[];//可以这样
int[] a;//也可以这样
但是要注意一下,int a[],i;和int[] a,i;是不一样的:a都是数组没问题,但是第一种那里的i是整型,而第二种那里的是数组!!!
- 用于数组的逐元循环的for语句:
- 比如:
int fib[]=new int[n];
for(int value:fib)//这个就是了
System.out.println(value);
这里的value就会依次获得数组的值。要注意value的类型要和数组的类型一样。
数组的引用模型:
数组是一个引用类型,所以它传值给方法之后,方法体里面是可以改变数组的元素的。来一个对比看看。int a=1,b;先让b=a;这个之后b=a=1了,然后再调用方法addOne(b);之后,b=1+1=2;但是a还是为1;再看看数组的:int a[]={1,2,3,4,5},b[];让b=a(这就是引用赋值了);再b[0]=999;这时候a[0]也变成了999了。就像C++里面的指针一样,a,b都指向了同一个数组.
- 二维数组:
int array[][]=new int[5][6];
System.out.println(array.length);//输出5,即二维数组的行数
System.out.println(array[0].length);//输出6,即二位数组的列数
//不规则的二维数组
int arr[][]=new int[3][];//申请了第一维的空间
arr[0]=new int[3];//这里二维数组的第一行就有3个int空间了
arr[1]=new int[6];//这里二维数组的第二行就有6个int空间了
4) 参数的传递:
- 基本数据类型—》传值
- 引用数据类型—》传引用
- 常量形参:
public static void functionA(final int n){
//声明n为常量,方法体里不能赋值
n=10;//这样是错的,不能对常量赋值
}
public static void functionB(final int arr[]){
//声明数组为常量,在方法体里面不能更改引用
arr[0]=10;//可以,更改的是数组元素
arr = new int[4];//不行,不能对常量赋值,即不能改变数组的引用
}
- 可变形参:向一个方法传递可变数目的元素,除了数组参数,还可以通过可变形参实现。在形参类型后面加”…”就表示改形参数目可变(也就是把它当做一个数组)。但是可变形参只能用在最后一个形参位置,并且一个方法最多只能有一个可变形参。比如:
public static void print(int... value);//可变形式参数,可将value视为int[]类型
【注意】在方法重载中,重载方法之间必须以参数列表相区别,不能以返回值相区别!!!因为在编译时,编译器是根据方法实际参数的数据类型、个数和次序来确定执行重载方法的哪一个。
第二天
- 对象引用模型:首先看看一个测试代码
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Year y1 = new Year(2020, 1, 1);
y1.print();//输出是
Year y2 = y1;
y2.print();
y2 = new Year();
y2.print();
y2.set(y1);
y2.print();
}
}
class Year {
private int year;
private int month;
private int day;
public Year(int year, int month, int day) {
super();
this.year = year;
this.month = month;
this.day = day;
}
public Year() {
this.year = 2017;
this.month = 1;
this.day = 1;
}
public void set(Year y) {
this.year = y.year;
this.month = y.month;
this.day = y.day;
}
//也可以是拷贝构造函数,效果同上
// public Year(Year y){
// this.year = y.year;
// this.month = y.month;
// this.day = y.day;
// }
public void print() {
System.out.println(year + " " + month + " " + day);
}
}
总结一下:如果两个对象之间是赋值,如上代码中的y2=y1,这时候y2是不会开辟空间的,y1和y2指向同一个对象,但是用了new后就会给它开辟空间,y2=new Year();y2就有了自己的地盘了。这就像是C++里面的一样,只要有新对象产生就会有空间的开辟。记住,有new就开辟。
**【拓展一下】**return this.year+’-‘+this.month+’-‘+this.day;和
return return this.year+”-“+this.month+”-“+this.day;的区别:前一个返回值是int后一个是String,不信可以试试。
2.对象关系和比较运算(都是boolean):
instanceof运算符是判断一个对象所引用的实例是不是属于某个类。比如上面的代码,y1就属于Year,所以 y1 instanceof Year;就是true咯。
基本数据类型的比较:比如int,float,double等等,都是只比较两个变量的值是不是相等。
- 对象比较:这个又有两种比较了。第一种就是形如 y1==y2;第二种就是y1.equals(y2)。让我们回到上面的图一看看,如果是情况一这样,那么两种方法都是true了,但是情况二中两个都是false。可以加上这两行代码测测。
System.out.println(y1==y2);
System.out.println(y1.equals(y2));
3.静态成员:
静态成员属于类,即使没有创建实例,也可以通过类名访问静态成员变量/方法。在静态成员方法体中,不能访问实例成员,不能使用this引用!!!!!!!!
同名的实例方法被覆盖,同名的静态方法被隐藏。它们的区别在于:子类对象转换成父类对象后能够访问父类被隐藏的变量和方法,而不能访问父类被覆盖的变量和方法。子类如要访问父类中被隐藏的实例变量,则需要使用super关键字;如果要访问父类中被隐藏的类变量,则需要用父类的名字加“.”来访问。
还是看个例子好:
//file name:Parent.java
public class Parent {
protected static String kind = "This is Parent class";// 这是类变量
protected static int age = 50;// 这是类变量
protected String name = "Parent"; // 这是实例变量
/**
* 静态方法
*
* @return 返回Parent的kind
*/
public static String getKind() {
System.out.print("Parent.getKind():");
// return this.kind;//错误
return kind;
}
/**
* 静态方法
*
* @return 返回Parent的age
*/
public static int getAge() {
System.out.print("Parent.getAge():");
return age;// 如果是this.age,错误
}
/**
* 实例方法
*
* @return Parent的name
*/
public String getName() {
return this.name;
}
/**
* final方法
*
* @return age+1
*/
public final int nextAge() {
return ++age;
}
}
//file name:Child.java
public class Child extends Parent {
protected static String kind = "This is CHild class";
protected int age = 25;// 实例变量,这个和Parent中不同
protected String name = "Child";
/**
* 静态方法,隐藏了Parent中的方法
*
* @return child中的kind
*/
public static String getKind() {
System.out.print("Child.getKind():");
return kind;
}
/**
* 静态方法
*
* @return 父类的名字
*/
public static String getParentKind() {
// 通过父类名加.访问
return Parent.kind;
}
/**
* 实例方法
*
* @return Child的name
*/
public String getName() {
return this.name;
}
/**
* 实例方法
*
* @return Parent中的name
*/
public String getParentName() {
return super.name;
}
// //这样是错的,因为实例方法不能覆盖父类的静态方法
// public int getAge(){
// return this.age;
// }
// 这样也是不行的,父类中的final方法不能够被覆盖
// public int nextAge(){
// return ++age;
// }
public static void main(String[] args) {
// TODO Auto-generated method stub
Child child = new Child();
System.out.println("child name:" + child.name + ";age:" + child.age + ";kind:" + child.kind);
Parent parent = child;// 将child类型转换成Parent对象
System.out.println("After name:" + parent.name + ";age:" + parent.age + ";kind:" + parent.kind);
System.out.println();
System.out.println("child.getParentName():" + child.getParentName());
System.out.println("child.getParentKind():" + child.getParentKind());
System.out.println();
child.getName();
child.getKind();
parent.getName();
parent.getKind();
}
}
第三天
- 抽象类:
- 使用关键字abstract声明的类称为抽象类,使用abstract声明的成员方发称为抽象方法。
- 构造方法、静态成员方法不能被声明为抽象方法。
- 抽象类中可以有非抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象方法中也有构造方法,而且如果有某个类继承了该抽象方法,需要给该抽象类提供参数以初始化。
- 最终类:
- 使用关键字final声明的类就是最终类。
- 最终类不能被继承,即不能有子类。
- 最终类中包含的都是最终方法;非最终类也可以有最终方法。
- 最终方法不能被子类覆盖。
- 接口:
- 接口是一种(引用)数据类型。
- 接口中的成员变量都是常量(变量名全部大写),声明时必须赋值,默认修饰符为public static final,不能声明实例成员变量。
- 接口中的成员方法都是抽象的实例成员方法,默认修饰符为public abstract,不能声明为static。(特别注意,如果某个类实现某个接口,必须加上public,如图)
- 接口不能包含构造方法,因为构造方法不能是抽象的。
- 接口的访问控制权限是public或缺省。
- 接口可以多重继承。
- 一个类可以实现多个接口,多个接口之间用逗号分隔。
- 一个非抽象类如果声明实现多个接口,那么它必须实现(覆盖)所有指定接口中的所有抽象方法,方法的参数列表必须相同,否则它必须声明为抽象类。