类
对象
比如,可以将类比作是一辆汽车的设计图纸,一辆辆汽车就是根据这个类生产出的对象:
class
关键字;比如定义一个Car类:
class Car { //Car类的属性 int number; //车辆编号 //Car类的方法 void go() { //类中的方法访问类的属性 System.out.printf("My number is %d, go go go!", number); } }
在主方法中创建一个Car类的对象并访问其成员和方法:
class CarTest { public static void main(String[] args) { //创建一个动态对象 Car testCar = new Car(); //访问对象的属性并修改 testCar.number = 1; //调用对象的方法 testCar.go(); } }
编译运行:
javac CarTest java CarTest
运行结果:
!!!
这里说的内存指的是程序运行时占用的内存,可以理解为RAM空间。
!!!
javac CarTest
,生成的CarTest.class
可执行程序保存在硬盘上;java CarTest
命令后,操作系统将整个程序加载到内存中,准备运行;类只是一个概念,是抽象的,用来模拟一个事物,这里用来模拟一个车辆,所以类不会占用任何内存空间。
Car testCar = new Car();
Car()
函数称为Car类的构造函数,虽然我们并没有定义,但是这个函数是默认存在的,在创建一个该类对象时自动调用,在第4节具体讲述;new
关键字表明这个对象创建时内存空间要动态分配,所以一个new出来的对象其内存空间在堆中,new
关键字的作用和C语言中malloc
函数的作用相同,只不过更为简单,总结:系统按照类中的定义在堆中分配内存,然后将首地址返回;如上图所示,如果我们想要访问堆中Car对象的number属性和go方法,该如何访问呢?
显然,我们不可能直接去访问,车到山前必有路,testCar变量中保存着Car对象的首地址,所以,我们有了testCar变量后无所不能!
如上面的演示程序,直接通过testCar.nunber
就可以访问number属性,通过testCar.go()
就可以访问go方法。
在创建一个对象时,系统首先会为该对象分配内存,然后自动调用该类的构造函数。
在创建对象时,我们调用了Car()
函数,但是这个函数在我们的类定义中并没有,那么这个函数是如何调用的呢?
Car testCar = new Car();
这里的Car()
就是Car类
的构造函数,在我们定义了Car类
后,系统会自动生成默认构造函数Car()
。
自定义构造函数的时候,需要注意构造函数有以下特点:
比如,这里我自定义一个无参构造函数和带参构造函数:
class Car { //Car类的属性 int number; //车辆编号 //无参构造函数 public Car() { System.out.printf("无参构造函数被调用.\n"); } //有参构造函数 public Car(int i) { number = i; System.out.printf("有参构造函数被调用.\n"); } //Car类的方法 void go() { //类中的方法访问类的属性 System.out.printf("My number is %d, go go go!\n", number); } }
使用无参构造函数和有参构造函数分别创建对象:
class CarTest { public static void main(String[] args) { //使用无参构造函数创建一个动态对象 Car testCar1 = new Car(); //访问对象的属性并修改 testCar1.number = 1; //调用对象的方法 testCar1.go(); //使用有参构造函数创建一个动态对象 Car testCar2 = new Car(2); //调用对象的方法 testCar2.go(); } }
运行结果如下:
为了验证“当我们自定义构造函数,系统是否会再自动生成默认构造函数?“”,我们将无参构造函数去掉,再次运行,系统报错,提示默认无参构造函数没有定义:
所以我们可以得出:
一旦自定义构造函数,系统不会再自动生成默认构造函数。
对于类中的数据成员(类的属性),系统先执行定义时赋的初值,然后再执行构造函数中赋的初值。
比如,我在定义时将number
属性赋值为1,构造函数中赋值为2,最后的结果为2:
class Car { //Car类的属性 int number = 1; //车辆编号 //无参构造函数 public Car() { System.out.printf("无参构造函数被调用.\n"); } //有参构造函数 public Car(int i) { number = i; System.out.printf("有参构造函数被调用.\n"); } //Car类的方法 void go() { //类中的方法访问类的属性 System.out.printf("My number is %d, go go go!\n", number); } } class CarTest { public static void main(String[] args) { //使用有参构造函数创建一个动态对象 Car testCar = new Car(2); //调用对象的方法 testCar.go(); } }
运行结果: