java是面向对象的语言: “万物皆对象”: 任何事物都可以使用类进行描述。
需求: 使用java类描述 一个婴儿.
在现实生活中有两种婴儿, 一种婴儿一出生就具备了名字(有身份),还有一种婴儿就是出生之后才有名字的(黑户)。
那么如何才能成为有身份的baby呢?引入构造函数。
一、构造函数:
1、作用: 给对应的对象进行初始化。
2、构造函数的定义的格式:
修饰符 函数名(形式参数){
函数体...
}
3、构造函数要注意的细节:
1)构造函数是没有返回值类型的。
2)构造函数的函数名必须要与类名一致。
3)构造函数并不是由我们手动调用的,而是在创建对应的对象时,jvm就会主动调用到对应的构造函数。
4)如果一个类没有显式的写上一个构造方法时,那么java编译器会为该类添加一个无参的构造函数的。
5)如果一个类已经显式的写上一个构造方法时,那么java编译器则不会再为该类添加 一个无参的构造方法。
6)构造函数是可以在一个类中以函数重载的形式存在多个的。
4、疑问一:创建对象时,jvm就会调用到对应的构造方法,那么我们以前没有学构造方法,那么以前创建对象时,jvm是否也会调用构造方法呢?如果有?构造方法从何而来呢?
1)答:会调用, java编译器在编译的时候给加上去的。
2)jdk提供了一个java开发工具(javap.exe)给我们进行反编译的。
javap 反编译工具的使用格式:
javap -c -l -private 类名
代码:
class Baby{
int id;
String name;
public void cry(){
System.out.println("嚎啕大哭");
}
}
class Demo1{
public static void main(String[] args){
Baby b1 = new Baby();
b1.id = 1;
b1.name = "豆豆";
System.out.println("身份:"+b1.id+",名字:"+b1.name);
}
}
效果及反编译结果:
5、疑问二: java编译器添加的无参构造方法的权限修饰符是什么?
答:与类的权限修饰是一致的。4、中的例子,class Baby没有任何修饰符,而反编译中java编译器默认生成的无参构造方法也没有修饰符。如果给类前添加一个public,那么无参构造方法也会自动加上public。
6、构造函数与普通函数的区别:
1)返回值类型的区别:
a)构造函数是没有返回值类型的,
b)普通函数是有返回值类型的,即使函数没有返回值,返回值类型也要写上void。
2)函数名的区别:
a)构造函数的函数名必须要与类名一致,
b)普通函数的函数名只要符合标识符的命名规则即可。
3) 调用方式的区别:
a)构造函数是在创建对象的时候由jvm调用的。
b)普通函数是由我们使用对象调用的,一个对象可以调用多次普通 的函数,
4)作用上的区别:
a)构造函数 的作用用于初始化一个对象。
b)普通函数是用于描述一类事物的公共行为的。
二、构造代码块:
可以看出来,自定义的构造方法仅仅是使得符合(new Baby(int i,String s))这种形式的对象进行了初始化。
1、对比构造代码块、构造函数的作用
1)构造代码块的作用:给对象进行统一的初始化。
2)构造函数的作用: 给对应的对象进行初始化。
2、构造代码块的格式:
{
构造代码块
}
注意:
1)构造代码块的大括号必须位于成员位置上。
2)构造代码块是在创建了代码块所属类的对象时调用一次。
3、代码块的类别:
1)构造代码块。
2)局部代码块:大括号位于方法之内。 使用的很少,作用很小。 作用:缩短局部变的生命周期,节省一点点内存。
3)静态代码块 static
4、构造代码块要注意的事项:
代码:
class Demo1{
//构造函数
public Demo1(){ //构造函数
i = 300000000;
}
//构造代码块 //构造代码块的初始化
{
i = 200000000;
}
int i = 100000000; //成员变量的显示初始化
public static void main(String[] args)
{
Demo1 d = new Demo1();
System.out.println("i = "+d.i);
}
}
1)java编译器编译一个java源文件的时候,会把成员变量的声明语句提前至一个类的最前端。
2)成员变量的初始化工作其实都是在构造函数中执行的。
3)一旦经过java编译器编译后,那么构造代码块的代码块就会被移动到构造函数中执行,是在构造函数之前执行的,而构造函数中的代码是最后执行的。
4) 成员变量的显示初始化与构造代码块的代码是按照当前代码的顺序执行的。
对比: