文章目录
一、constructor
I skipped it!
二、overload
1、是否重载,与返回值类型无关,只与参数列表有关,另外:
public void m1(Integer integer) {}
与
public void m1(int i ){}
也能构成overload。
2、以基本类型作为参数的overload,当传入的数据类型(实际参数类型)“小于”形参,实际数据类型就会被提升。
三、this 关键字
1、先抛个问题:
编译器是如何知道Peel是被 a 还是b 所调用?
public class BananaPeel {
public static void main(String[] args) {
Banana a = new Banana();
Banana b = new Banana();
a.peel(1);
b.peel(2);
}
}
class Banana{
void peel(int i) {
}
}
原来,编译器做了一些额外的工作,它把“所操作对象的引用传递作为第一个参数传递给了Peel()”,所以实际的内部调用形式是:
Banana.peel(a,1)
Banana.peel(b,2)
若希望在方法内部获取对当前对象的引用(或者叫:调用方法的按个对象的引用),可使用this关键字来表示
2、 再举个例子
这个例子通过this返回了对当前对象的引用,使得容易在一条语句中对同一个对象执行多次操作
public class Leaf {
int i = 0;
Leaf increment() {
i ++;
return this;
}
void print() {
System.out.println("i = " + i);
}
public static void main(String[] args) {
// 由于 increment()返回的原来调用方对象的引用,所以下例中 leaf 与leaf1 其实是同一个对象
// 如此,很容易在一条语句中对同一个对象执行多次操作
Leaf leaf = new Leaf();
Leaf leaf1 = leaf.increment().increment().increment();
System.out.println(leaf == leaf1);
leaf.print(); // i = 3
leaf1.print();// i = 3
}
}
下面这个例子使用this关键字将当前对象传递给其他方法,
实际生产中,大概没人这样写的的吧?
public class Person {
public void eat(Apple apple) {
Apple peeledApple = apple.getPeeledApple();
System.out.println(" eated it!");
}
}
// “削苹果”的工具类。由于某种原因,必须要将该工具类放置到Apple外部,比如该外部方法要应用于许多不同的类,但我们不想重复
// 这些代码
class Peeler{
static Apple peel(Apple apple) {
/*peel process*/
return apple;
}
}
// 传入一个苹果,返回“削完”后的苹果,但是****其实还是同一个苹果****
class Apple{
Apple getPeeledApple() {
// 传入的是一个this,即一个 Apple对象
return Peeler.peel(this);
}
}
class PassingThisTest{
public static void main(String[] args) {
new Person().eat(new Apple());
}
}
四、this用于构造器调用
使用this可在一个构造器中调用另一个构造器,以避免重复代码。
在普通方法中,this指的是“这个对象”或者“当前对象”,而其本身表示对当前对象的引用。而在构造器中,this后有了参数列表,则含义不同,那将表示对符合该参数列表的某个构造器的调用。
需要注意的是,构造器中调用this() ,必须将该句放置在构造方法中的第一行。
public class Flower {
int petalCount = 0;
String s = " initial value ";
public Flower(int petalCount) {
System.out.println("----");
this.petalCount = petalCount;
}
public Flower(String s) {
System.out.println("+++++");
this.s = s;
}
public Flower(int petalCount, String s) {
this(petalCount);
this.s = s;
System.out.println("......");
}
public Flower() {
this(10, " hana ");
System.out.println(" no-param constructor ");
}
public static void main(String[] args) {
Flower flower = new Flower();
System.out.println(flower.petalCount);
System.out.println(flower.s);
}
}
五、清理对象和GC
TODO
六、初始化
6.1 成员初始化
两点:
1、局部变量,必须手动初始化
2、全局变量,即使不手动初始化,编译器也会赋初始值
6.2 构造器初始化
6.2.1 初始化顺序
略
6.2.2 静态数据初始化
1、无论创建多少个对象,静态数据只占用一份内存
2、先初始化静态对象(如果之前没有初始化的话),然后初始化“非静态对象”
6.2.3 静态代码块
1、只执行一次!随着类的加载而加载
6.2.4 代码块(实例初始化)
在实例化每个对象时,代码块中的代码 一定会执行,不论是使用无参还是有参构造器来初始化,而且 代码块中的代码在 构造器之前执行。
所以总的来说:初始化顺序是:
类变量 --> 静态代码块 --> 构造器 --> 代码块
七、数组初始化
数组的创建是在运行时进行的。
数组元素中的基本数据类型会自动初始化为空值,对于布尔值,即为FALSE;对于数字和字符,即为0;
而对于元素是引用类型的数组,其元素会自动初始化为null。