Java是面向对象的编程语言,其思想为将现实世界的实物抽象为对象,然后考虑这个对象具备哪些属性及行为。
类与对象的概念
类:类是对同一类事物的属性及行为(方法)的封装。
对象:对象是类的一个具体的实例。就比如,人类是所有的人的统称,而我们自己就是人这个类的一个具体的实例。
类与对象在代码中的使用
在Java中,类用关键字class来声明。声明格式为:class 类名{}
比如:
class Person{
}
类名的首字母建议大写
在类中,我们可以定义类本身所具有的一些属性及行为。比如说人,人所具有的属性有姓名,性别及年龄等,人的行为有结婚等等。所以,我们的Person类还可以添加一些属性及方法让他具象化一点。
class Person{
/*
* 属性作为类的成员变量来声明
*/
//姓名
public String name;
//年龄
public int age;
//性别
public String sex;
/*
* 结婚的行为,我们以一个方法来定义
*/
pubic void marry(){
System.out.println("name: " + name + "; age: " + age + "; sex: " + sex);
}
}
现在我们的Person类就算定义好了,但是接下来怎么用它呢?如果不知道怎么用,别说结婚,连对象都没有!!!诶?对象?作为一个程序员,怎么可能没有对象?现在没有,那就new一个呗。
我们先看一下生成对象的代码格式:
类名称 对象名称 = new 类名称();
Person person = new Person();
这样,我们就有了一个Person的实例,也就是Person类的一个对象。有了对象之后,我们就可以操作类中的非私有的属性和方法。操作方式为:
对象名.属性:调用类中的某个属性。
对象名.方法名:调用类中的某个方法。
我们现在写个小例子:
public class PerosnDemo {
public static void main(String args[]) {
// 声明并实例化一个Person对象
Person personZhang = new Person() ;
//给personZhang一个名字
personZhang.name = "张麻子" ;
//给personZhang设置年龄
personZhang.age = 25 ;
//给personZhang一个性别
personZhang.sex = "男";
//调用类中的marry()方法
person.marry() ;
//我们再实例化一个Perosn对象
Person personWang = new Person() ;
//给personWang一个名字
personWang.name = "王翠花" ;
//给personWang设置年龄
personWang.age = 20;
//给personWang一个性别
personWang.sex = "女";
}
}
输出结果为
name: 张麻子; age: 25; sex: 男
现在,有的同学有疑问了。在Java中,是怎么给对象赋值的呢?在赋值的时候会不会出错,把张麻子变成女的,把王翠花变成男的?要明白这个问题,我们就的看看Java中是怎么给对象分配存储空间的。
内存解析
分析内存分配之前,我们先简单了解两个概念:
栈内存(Java虚拟机栈):Java中基本类型的成员变量以及对象的引用(保存的信息可以推导出其对象的堆内存地址)等都放在这里。
堆内存:存放对象的属性,new出来的对象都在这里。
现在,我们来分析一下上面代码在内存中的分配:
由上图可见,当实例化一个对象时,Java虚拟机会为这个新生的对象分配内存,在堆上给他开辟一块空间。在栈上保存这个对象的引用,引用中含有对象在堆内存中的物理地址(其实不是,但可以这么理解)。每当我们给这个对象赋值的时候,我们会通过引用所包含的物理地址信息,找到堆上的这个对象,并对其做相应了修改。不同的对象持有不同的堆内存地址。所以,不会出现我们之前说的两个person性别错乱的问题。
那么,两个对象能不能持有一个相同的引用,或者说能不能指向同一个地址空间?答案是可以的。比如,我们这么写:
personWang = personZhang;
这样,personWang的引用就会指向personZhang的地址空间。
这样,两个Perosn类的对象就指向了同一个堆内存空间,对其中一个对象做修改,另一个对象也会做相应的变化。
而perosnWang之前所指向的堆内存上的空间,因为没有了对象的引用,就会变成垃圾,等待GC的回收。