类似于“书要越读越薄”的感觉,
这篇文章中只写每个知识点的记忆点!
每一条1)2)3)就是一个记忆点!
1、面向对象
面向对象的三大特性:封装、继承、多态
前两个很好理解,重点是多态。java中多态分为两种,一种是函数的重载,另一种是子类的重写。这一点和C++中是相同的。
2、this指针
this指针在C++中有如下两个作用
在java中也一样,只不过java实现链式编程时,return的是this
3、构造函数(同C++)
1)构造函数的3个特点
- 没有返回值也不写void
- 函数名与类名相同
- 可以重载
2)一旦自己写了构造函数,编译器就不提供默认的构造函数了。
在下面的例子中,这种情况会报错。
文件(一)Hello.java
public class Hello {
String morning;
Hello(String morning){
this.morning=morning;
}
}
文件(二)主类.java
由于我们自己写了一个构造函数,编译器不提供默认构造函数了,那么这个时候再new Hello(),参数为空,就会报错。避免的措施就是,一旦我们自定义了有参构造,就(必须、最好)再自己写一个默认的无参构造函数(同C++)。
文件(一)Hello.java
4、由于垃圾回收机制的存在,java没有析构函数
5、对象的内存模型
注意对象的引用和对象的实体这两个概念。
5.1 声明对象后的内存模型
假如我们有一个Person类,有String name,int age,double height3个成员变量。
Person p;
这时p是一个空对象(说是空引用更好理解一些),它的值默认为null。
5.2 创建对象后的内存模型
p = new Person();
1)为name、age、height各个变量分配内存
2)为name、age、height各个变量进行初始化。(如果有构造函数按照构造函数进行,没有就默认用惰性值还记得吗)
3)计算出一个称为引用(可以看做地址)的值,把该引用赋值给p。
在C++中,我们用一个指针去接收new出来的值,例如
int *p = new int(10);
所以java中的引用可以看作指针或地址
5.3 垃圾回收机制 —— 自动回收堆区new出来的
对象的引用存在栈区中(Person p和其他局部变量一样存放在栈区),对象的实体存放在堆区(new出来的都存放在堆区)。
在C++中,由编译器自动管理栈区。由程序员手动管理堆区(new 和 delete)。
java的垃圾回收机制自动收走堆区中不再被引用指向的实体,不需要程序员手动管理了。
下面用内存模型解释一下什么叫“不再被引用指向的实体”
Person p1 = new Person("jj",18,162.5); Person p2 = new Person("hh",25,174.0);
p2 = p1;
上图中右边被框起来的就是不再被引用指向的实体。
总结起来就一句话,java自动管理堆区和栈区。
注意:
比如,我们自己new出来的FileReader对象,使用完后要调用close方法关闭。
5.5 java中引用和C++中引用的区别
我认为java中的引用和C++中的引用不能记成一个概念,java中的引用更多的是“地址”的意思。
- 在C++中,只需要记住一句话“引用是变量的别名”,基本数据类型可以有引用int &m=a,对象也可以有引用。在java中,分为引用数据类型和基本数据类型,从命名就能看出,只有引用数据类型能使用引用,基本数据类型不能。
- 在C++中,引用的本质是“指针常量”,既然是常量那么就不能改变,也就是说不能再给引用赋第二个值。
int &m=a; m=b; //错误!
在java中,引用是可以被重复赋值的(所以java中的引用理解成“地址”更好)。
Person p = new Person("jj");
p = new Person("hh"); //这是可以的!
6、类与程序的基本结构
1)最好是源文件都保存在相同的目录中。
2)如果非要不放在相同目录中,那么编译好的字节码文件和主类的字节码文件必须放在相同目录中
3)如果主类所在的源文件和其他源文件在同一目录,那么可以只编译主类所在的源文件,运行时会自动编译其他源文件。
7、参数传递——java只有值传递
java只有值传递,没有C++中的引用传递&,java认为这样更安全。
结论:基本数据类型传递的是里面的数值,引用数据类型传递的是地址值。
7.1 传基本数据类型
可以将低级别的传给高级别。例如:
void add(double a,double b){
}
可以传递double型和比double型级别更低的数据类型,比如:
add(10, 12);
7.2 传引用数据类型
“当多个引用(地址)指向同一实体时,所有的引用(地址)都能操纵这个实体,具有不变性的String除外”。
在下面这段程序中,battery和nanfu这两个引用一个是形参一个是实参,指向同一个实体,都可以操纵这个实体。
7.3 解释一下java中只有值传递
public static void main(){
person1 = new Person("aa");
person2 = new Person("bb");
swap(person1,person2);
//swap之后,person1依然指向"aa",person2依然指向"bb"
sout(person1.getName());
sout(person2.getName());
}
public static void change(Person person1, Person person2){
person temp = person1;
person1 = person2;
person2 = temp;
}
7.4 可变参数
1)语法
参数个数可以灵活变化。
void add(int x,int ... y)
但是下面这种是不对的,可变参数必须放在最后!
void add(int ... x,int y)
这一点和C++对于默认参数的规定有异曲同工之处,但是需要注意的是java不允许存在默认参数 。
2)提供x.length
public int add(int ...x){
int sum=0;
for(int i=0;i<x.length;i++){
sum=sum+i;
}
return sum;
}
3) 提供增强的for语句
public int add(int ...x){
int sum=0;
for(for i:x){
sum=sum+i;
}
return sum;
}
8、对象的组合—— 类A使用类B的对象作为其成员变量。
我们直接借助一个例子去看内存模型的变化。
Circel.java
Cicular(圆锥).java
主类.java
我们主要是看其中【代码4】【代码5】【代码6】之后内存模型的变化。【代码4】之后,
【代码5】之后,
【代码6】之后,
9、类的关联关系和依赖关系
其实这两个关系在上面的例子中已经涉及到了。
1)类的关联关系就是类的组合,即刚刚说过的类A使用类B的对象作为其成员变量。
2)类的依赖关系,A类中某个方法的参数是B类的对象(南孚电池那个例子),或者,A类中某个方法的返回值是B类的对象。
10、 方法重载
和C++的记忆点相同:
- 函数名相同,参数不同
- 仅返回值类型不同 不是重载
仅有一点不同,因为java不允许形参默认参数,所以不会出现C++中的歧义
void func(int a, int b=10){ } void func(int a){ } func(10) //编译器分不清到底应该调用哪个勒?
但是你以为这样就不会存在歧义了吗?
void func(double m, int n){
}
void func(int m, double n){
}
func(10,10); //前面讲过,可以向double传递int类型的值。所以现在编译器分辨不出应该用哪个方法了
这种歧义只能由程序员去避免。
11、访问权限
对于变量和方法:
- public:类内访问,类外也可以访问
- private:类内访问,类外不可以访问
- protected:类内访问,类外也可以访问(必须在同一包内。可以这样理解:一个项目分为许多包,让不同的程序员去完成不同的包,protected的类就意味着我自己写的类只能我自己的代码调用)
- 友好:同protected
友好:不加public、private、protected任何一个修饰
访问权限由高到低:public->protected->友好的->private
对于类:
- public类:可以在任何一个类中使用public类
- 友好类:只能在同一包中使用友好类
12、对象数组
这个概念我最初接触到是在用C++写todolist的时候,
Todo todolist[100]; //大小为100的对象数组 /*----创建几个todo对象进去----*/ todolist[0] = Todo(2,false,NOW,"go to shopping",false); todolist[1] = Todo(3,true,NOW,"submmit homework",false); todolist[2] = Todo(4,false,NOW,"have dinner",false);
在java中是一样的。
Todo todolist[] = new Todo[100]; //①声明、②创建对象数组,但是未进行③初始化
todolist[0] = new Todo(2,false,NOW,"go to shopping"); //创建对象
todolist[1] = new Todo(3,true,NOW,"submit homework"); //创建对象
todolist[2] = new Todo(4,false,NOW,"hava dinner"); //创建对象
but在java的实际开发中,我们不用对象数组,而用“集合”
13、包
- 包的本质就是文件夹。在两个包下可以有相同命名的java文件
- 一般利用公司名的倒置作为包名。
- 下面这种包结构下,如果在demo01的Main中import进来demo02中的Main,会报命名冲突的错误
pacakge com.test.demo01; import com.test.demo02.Main; //命名冲突 class Main{ }
- com
- test
- demo01
- Main
- demo02
- Main