- 编程代价高昂的主因:不安全的编程方式
- C++引入
构造器
(constructor),对象被创建时自动调用的特殊方法- Java也采用构造器,同时引入
垃圾回收器
构造器确保初始化
- 通过构造器,确保每个对象在被操作之前都能得到初始化
- 构造器为什么要与类的名称相同?
- 任何名字都可能与类的某个成员名称相冲突
- 需要让编译器知道该调用哪个方法来初始化这个对象(调用构造器是编译器的责任)
- 实质上也就是沿用了C++的解决方法
- 因此在编码风格(方法首字母小写)的角度上来看,构造器的命名是个例外
- Java中,初始化与创建
捆绑
方法重载
方法的重载能够减少语言的
冗余性
,倘若没有方法的重载,构造器也就难以实现,我们需要与编译器之间约定构造器方法的名称,让编译器知道调用哪个方法,由编码者来命名的话,便会有很多不同的名称,如果采用匹配的方案来实现的话,比如:类名为Car,将自己写的构造器命名为CarOne(),用类似匹配Car*的方式,如果写的方法一多,也就难免重复,带来诸多麻烦。总之:构造器是强制重载方法的另一个原因
重载方法的区分
- 独一无二参数类型列表
- 个数不同
- 顺序不同 - 一般不这么做<-代码难以维护
- 类型不同
以返回值类型区分重载方法
void f(){}
int f(){return 1;}
能否区分调用方法依赖于用户调用的情况:
int x = f(); //能够区分
f(); //无法区分 (为了副作用而调用)
根据方法的返回值来区分重载方法是行不通的
默认构造器
如果没有定义构造器,编译器会自动创建一个默认的构造器(“无参构造器”)
this关键字
class Banana { void peel(int i){/*...*/} }
public class test {
public static void main(String[] args) {
Banana a = new Banana();
Banana b = new Banana();
a.peel(1);
b.peel(2);
}
}
上述代码,peel()如何知道被a还是b调用?
编译器将“所操作对象的引用”
作为第一个参数传递给peel()
所以实际上是:
Banana.peel(a, 1);
Banana.peel(b, 2);
这个引用是编译器引入的,为了能够在方法的内部获得当前对象的引用
,设立专门的关键字:this
构造器中调用构造器
class Banana {
private String name;
private double price;
Banana(double price){
this.price = price;
}
Banana(String name, double price){
this(price);
this.name = name;
}
public void info(){
System.out.println("name:" + name + ";price:" + price);
}
}
- 无法调用两个 <- 构造器必须置于最起始处
static的含义
- 没有this的方法
- static方法内不能调用非静态方法
- 没有创建任何对象的前提下能调用static方法(仅通过类本身)
class Tool {
public static void sayHi(){
System.out.println("hello.");
}
}
public class test {
public static void main(String[] args) {
Tool.sayHi(); //仅通过Tool类本身调用,而不是由Tool创建的对象
}
}
/* Output:
hello.
*/
清理:终结处理和垃圾回收
- Java里的对象并非总是被垃圾回收
- 对象可能不被垃圾回收
- 垃圾回收不等于“析构”
- 垃圾回收只与内存有关
垃圾回收->回收程序不再使用的
内存
Native Method 本地方法
垃圾回收器如何工作
- 在堆上分配对象的代价十分高昂
- Java的垃圾回收器能够提高对象的创建速度 -> 因此Java从堆分配空间的速度可以和其他语言从堆栈上分配空间的速度相媲美
一些垃圾回收机制:
- 引用计数
简单、慢
每个对象 一个 引用计数器,当有引用连接至对象,引用计数加1;垃圾回收器在含有全部对象的列表上遍历,发现某个对象的引用计数=0,就释放其空间
- 更快的模式
依据:任何“活”的对象 ---能追溯到---> 在堆栈或静态存储区之中的引用,在此区域遍历所有引用 ---能找到---> 所有的“活”的对象
如何处理找到的“活”的对象
- 停止-复制
先暂停程序的运行,将所有“活”的对象复制到另一个堆(旧地址需要映射到新地址)
缺点:效率低,耗空间
- 标记-清扫
找到活对象->标记,全部标记工作完成,清理开始,没有标记的对象被释放,重新整理剩下的对象(由于剩下的堆空间是不连续的)
在只产生少量垃圾的情况下,它的速度很快