1. 类之间的关系
关系 | 描述 | “” |
---|---|---|
依赖 | 一个类的方法使用或操纵另一个类的对象 | “uses-a” |
聚合 | 类A的对象包含类B的对象 | “has-a” |
继承 | 类A扩展类B | “is-a” |
2. 使用预定义类
要使用对象,首先要构造对象,使用构造器(构造函数)来初始化对象
一个对象变量包含一个对象的引用,或者包含一个特殊值null
1 | data a = new data();//它引用了新构造的对象 |
对象和对象变量有重要的区别
例如:
1 | Data deadline;//变量deadline不是一个对象,而且实际上它也没有引用任何对象 |
在java中,对象变量的值只是对存储在另外一个地方的某个对象的引用
对象变量并没有实际包含一个对象,它只是引用一个对象
java中的引用并不是c++中的引用,可以把java中的对象变量看做类似于c++中的对象指针。
java中的对象都存储在堆中。
值类型和引用类型
num是int基本类型变量,值就直接保存在变量中。str是String引用类型变量,变量中保存的只是实际对象对应的地址信息,而不是实际对象数据。
对于基本类型变量num,赋值运算符将会直接修改变量的值,原来的数据将被覆盖掉,被替换为新的值。对于引用类型变量str,赋值运算符只会改变变量中所保存的对象的地址信息,原来对象的地址被覆盖掉,重新写入新对象的地址数据。但原来的对象本身并不会被改变,只是不再被任何引用所指向的对象,即“垃圾对象”,后续会被垃圾回收器回收。
使用静态工厂方法来构造LocalData类,不是使用构造器!!
1 | LocalData newyear = LocalData.of(1999,12,31);//不使用构造器来构造 |
3. 用户自定义类
在一个源文件中只能有一个公共类,但可以有任意数目的非公共类。
构造器总是与类同名并且总是结合new运算符来使用
构造器没有返回值
警告: 不要在构造器中定义与实例字段(对象中的数据)同名的局部变量
1 | class Employee{ |
要小心使用null值
1 | String str = null; |
定义方法(成员函数)
在c++中,在类的外部定义方法要使用成员限定符::,而在内部定义则该方法会被设置为内联方法.
在java中,所有的方法必须在类的内部定义,但并不表示它们是内联方法,java虚拟机会自动进行优化。
字段访问器:只返回实例字段值
注意: 不要编写返回可变对象引用的访问器方法!
1 | class Employee{ |
方法可以访问所属类的任何对象的私有特性
4. final关键字的基本用法
在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)。
final修饰一个类时,表示这个类不能被继承。
修饰方法时,此方法不能被重写。
修饰变量,final成员常量表示常量,只能被赋值一次
1 | final int num = 50; |
修饰引用类型时,则在其初始化之后不能再指向其他对象了,但是该引用所指的对象的内容是可变的!
1 | final Date str = new Date(); |
当final修饰一个成员变量,必须要显示初始化,有两种初始化方式
1 | class Employee{ |
5. 静态字段
5.1. 静态变量
1 | class Employee{ |
现在每个Employee对象都有一个自己的id字段,但这个类所有的实例都共享一个nextid字段。
假如有1000个Employee类对象,就有1000个实例字段id,分别对应每个对象,但是只有一个静态字段nextid。
即使没有Employee对象,静态字段nextid也存在,它属于类,不属于任何单个对象。
5.2. 静态常量
1 | class Employee{ |
5.3. 静态方法
静态方法不是在对象上执行的方法,静态方法只能访问静态字段。
可以直接提供类名来调用静态方法,而不需要通过类对象的引用来调用
1 | class Employee{ |
在c++中,要使用成员访问符:: 来访问作用域之外的静态字段和静态方法
如Math::PI
在Java中则是Math.PI,功能上相同,语法不同
6. 方法参数
java方法参数中的对象引用是按值传递的,并不是按引用传递
方法参数总结:
方法不能修改基本数据类型的参数
方法可以改变对象参数的状态
方法不能让一个对象参数引用一个新的对象
7. 对象构造
7.1. 默认字段初始化
如果在构造器中没有显式地为字段设置初值,那么就会自动地赋值为默认值:数值为0,布尔为false,对象引用为null。
7.2. 无参数的构造器
如果写一个类时没有编写构造器,就会自动为你提供一个无参数的构造器,他会把所有的实例字段设置为默认值。
如果类中提供了至少一种构造器,但是没有提供无参数的构造器,那么构造对象时不提供参数是不合法的!
7.3. 显式字段初始化
在java中可以直接初始化类的实例字段
1 | class data{ |
但是在c++中只能在构造函数中初始化,这与java不同;并且java没有成员初始化列表这一功能。
7.4. 调用另一个构造器
可以用this在构造器中调用另一个构造器来初始化
1 | public Employee(double s){ |
7.5. 初始化块
初始化数据字段的方法有三种:
1.在构造器中设置值
2.在声明中赋值,显式赋值
3.利用初始化块赋值
1 | class Employee{ |
也有一种静态初始化块,只在第一次加载类时进行初始化
静态初始化块只会调用一次,随着类的加载而加载,(类只加载一次)
普通初始化块可以调用多次,随着对象的创建而加载
而对于他们的理解,我写了这么一组代码
1 | class test{ |
对于初始化的执行顺序,构造器一般在最后执行
静态初始化块 | 静态属性初始化 > 普通初始化块 | 普通属性初始化 > 构造器
7.6. 包
包相当于一个文件夹,将类组织在一个集合中
一个类可以使用所属包中的所有类,以及其他包中的公共类
标记为public的部分可以由任意类使用;标记为private的部分只能由定义他们的类使用,如果没有指定public或private,这个部分可以被同一个包中的所有方法访问。
7.7. 类设计技巧
1.保证数据私有,不要破坏封装性。
2.一定要对数据初始化。
3.不要在类中使用过多的基本类型,用其他的类替换使用多个相关的基本类型。
4.不是所有的字段都需要单独的字段访问器和字段更改器。
5.分解有过多职责的类。
6.类名和方法名要能够体现他们的职责。
7.优先使用不可变的类。