类的定义
现实世界中有各种各样的事物,它们都被我们归类并命名。例如生物学中将印度象(大象)归为象科;将老虎归为猫科等。Java作为一门面向对象程序设计语言,也在其语法中做了相关的表述,那就是类的概念。
Java的类描述了现实中事物的相同性质,将它们放在一起研究,这也符合了面向对象的程序设计思想。
类的定义也称为类的声明。类中含有两部分元素,分别是成员变量和成员方法。
//这是一个简单的类定义实例
public class Car{
String color; //成员变量
int number; //成员变量
public void run(){ //成员方法
System.out.println(color+number);
}
}
上面的Car这个类,简单的描述了所有车都具有的属性。
构造方法与对象
构造方法是一类特殊的方法,具有特殊的功能。构造方法名与类名相同,没有返回值,在创建对象实例的时候通过new运算符自动调用。构造方法的作用是用来创建类的对象的。例如在Car类中,我们可以像下面这样创建对象。
Car c = new Car();
但是我们看到,Car类中并没有与Car同名的方法,那为什么能创建对象会成功呢?因为每个类都必须至少有一个构造方法,如果程序员没有为类定义构造方法,系统会自动为该类生成一个默认的构造方法,这个构造方法对于程序员是不可见的。默认的构造方法的参数列表及方法体均为空,所以生成的对象各属性值也为空或者零。
一般来说,构造方法应为所有的成员变量赋初值,成员变量的值也称为对象的属性值。所以我们也可以自定义构造方法,以针对创建对象时遇到的不同情况
public class Car{
String color;
int number;
public Car(){
}
public Car(String c){
color = c;
}
public Car(int n){
number = n;
}
public Car(String c,int n){
color = c;
number = n;
}
public void run(){
System.out.println(color+number);
}
}
public class Test{
public static void main(String args[]){
//下面依次调用四个构造方法来创建对象
//Car c1 = new Car();
//Car c2 = new Car("red");
//Car c3 = new Car(53463);
Car c = new Car("black",23531);
}
}
上面的四个构造方法展示了创建对象时所有会发生的情况,我们可以通过构造方法的选择,来对对象中的两个成员变量经行操作。
注意:如果类定义中已经含有一个或者多个构造方法,则系统不会再自动生成默认的构造方法了,所以最好再自己写一个参数列表为空的构造方法,这样调用new Car()时就不会出现编译错误。
实际上,类的定义相当于一个“模子”,对象的创建过程就像是拿着“模子”复制了一个个副本。
Car c; //声明Car类型的变量,并在内存中建立了一个引用
c = new Car(); //创建对象,并将对象在内存中的首地址赋给c引用
调用new为对象在内存中分配空间,要调用类的构造方法。在Java中,使用构造方法是生成实例对象的唯一途径,这个过程称为对象的实例化。上面的代码说明一个声明一个变量仅仅是“预定”了变量的存储空间,只有进行对象的实例化后,内存中才会有对象的存储空间。
下面我们看一段具体的代码,并简要给出其内存图解:
public class Car{
String color;
int number;
public void run(){
System.out.println(color+number);
}
}
public class Test{
public static void main(String args[]){
Car c = new Car();
c.color = "red";
c.number = 678;
}
}
栈内存:运行方法
堆内存:存储对象的容器
下面对图解简单阐述
当执行创建对象的代码时,对象的成员变量跟随对象进入堆内存中,并赋默认值,系统把对象在堆内存中的首地址(此处假设是0x1234)传给Car类型的变量c,c就会指向相应的堆内存空间,此时变量c就获得了管理堆内存中成员变量的“资格”。所以执行蓝框中的代码,即是通过c变量去间接修改了堆内存中的成员变量值。
在方法中使用成员变量时,其实省略了this关键字(Java用this关键字自动把成员和引用变量结合在一起,所以可以省略this)。this指的是调用run方法的对象,这里run()方法是由变量c调用的,而变量c又指向堆内存中的相应对象,所以方法run()中的color和number值也即是堆内存中相应对象的成员变量的值。