类的构造函数
构造函数在每个类中都存在,是面向对象设计语言(OOP)的特色。
特点:
- 函数名与类名是相同的
- 不能有返回值
- 可以有参数,也可以没有参数
- 可以有多个
说明:
- 声明一个对象,系统首先为该对象分配内存,然后立即自动调用该对象的构造函数
注意:
- 任何一个类对象被生成时候一定会调用该类的构造函数
- 无论一个类有多少个构造函数,生成一个类对象时一定只会调用其中的某一个构造函数!
class A
{
int i;
int j;
}
class TestMemo
{
public static void main(String[] args)
{
A aa = new A();
//运行此语句时,
//首先
//->(A *)malloc(sizeof(A));
//->new A();在堆中动态分配一块区域,被当作了A对象
//->aa本身的内存是在栈中分配的
//其次
//调用系统默认分配的class A()这个无形参的构造函数
//堆中内存的地址赋给了aa
//aa指向堆中的内存,aa代表了堆中的内存
//aa.i代表:aa这个静态指针变量所指向的动态内存中的A对象数据成员i
//
aa.i = 10;
aa.j = 20;
System.out.printf("%d, %d\n",aa.i,aa.j);
}
}
_________________________
程序运行示例:
10, 20
_________________________
这个程序表面上没有构造函数(实际上你懂的),但是程序可以正常运行。这是因为若没有人为的创建的构造函数,系统会自动为该程序创建无参构造函数
一旦人为的创建构造函数,系统就不再会自动为该程序创建无参构造函数
class A
{
int i;
int j;
public A(int a,int b)
{ //此处认为创建有参数的构造函数,系统就不再会为程序自动创建无参构造函数
System.out.printf("有参构造函数被调用了!");
}
}
class TestMemo
{
public static void main(String[] args)
{
A aa = new A();//(A *)malloc(sizeof(A));
//new A();在堆中动态分配一块区域,被当作了A对象
//aa本身的内存是在栈中分配的
//堆中内存的地址赋给了aa
//aa指向堆中的内存,aa代表了堆中的内存
//aa.i代表:aa这个静态指针变量所指向的动态内存中的A对象数据成员i
aa.i = 10;
aa.j = 20;
System.out.printf("%d, %d\n",aa.i,aa.j);
}
}
程序运行示例:
————————————————————————————————————
TestMemo.java:18: 错误: 无法将类 A中的构造器 A应用到给定类型;
A aa = new A();//(A *)malloc(sizeof(A));
^
需要: int,int
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
1 个错误
————————————————————————————————————
该程序就充分表现了一旦人为创建构造函数,系统就不再创建,可以理解系统是一个特立独行的人,别人干过的事情,它绝不会再干。
class A
{
private int i;
private int j;
/**
public B(int a,int b) /*error 函数名与类名必须是相同的*/
public void A(int a,int b) /*error ,构造函数不能有返回值,这是类A的一个普通的操作,不再是构造函数*/
*/
public A()
{
System.out.printf("一个类的构造函数可以有多个\n");
}
public A(int a,int b)
{
i = a;
j = b;
System.out.printf("有参构造函数被调用了!\n");
}
public void show()
{
System.out.printf("i = %d,j = %d\n",i,j);
}
}
class Main
{
public static void main(String[] args)
{
A aa = new A(1,2); //此处创建对象aa的同时,系统还会调用有参的构造函数public A(int a,int b)
A bb = new A(); //此处创建对象bb的同时,系统还会调用无参的构造函数 public A()
aa.show();
}
}
程序运行示例:
————————————————————————————————————
有参构造函数被调用了!
一个类的构造函数可以有多个
i = 1,j = 2
————————————————————————————————————
构造函数,只有构造此类对象的时候会调用!
几点要求:
1、此构造函数没有返回值,故严格上讲,不能称之为函数,void也不能加
2、一个类的构造函数可以有很多个,在类创建对象时候,根据A aa = new A( );中的
括号中形式参数的个数来匹配相应的构造函数
扩展补充
构造函数的返回值问题
-
在一个类中可以定义多个函数名与类名相同却有返回值的函数,函数为void或者int或者double都是可以的,
这些有返回值的函数只要能满足重载特点,就可以同时存在一个类中,不过要注意:这些有返回值的函数(包括返回值为void的函数)都不是构造函数,都不会像创建对象的同时调用构造函数那样被类对象自动调用。
-
当然也可以定义多个没有返回值的函数,注意连void都不可以加,这些函数才是构造函数,无返回值的函数才会被对象自动调用。
-
如果定义了有返回值并且方法名与类名相同的方法(类中的操作),程序并不会报错,但是容易产生歧义,所以强烈建议不要在构造函数的前面加返回值
构造函数数据成员的赋值问题
-
如果在定义的同时没有初始化,则它的值时系统自动分配好的默认值!
-
如果在定义数据成员的同时赋初值,则是可以的,也就是说该值是生效的,注意在C++中则不可以,在C++中一个类的数据成员不能在定义的同时初始化,它只能在构造函数中初始化
-
如果在定义数据成员的同时赋初值,当然生效,但如果在构造函数中又改变了定义时赋的初值,则该数据成员最终的值就是构造函数中修改之后的那个值,因为:系统先执行定义时赋的初值,然后再执行构造函数中赋的初值