一.JAVA类的定义
JAVA里面有class关键字定义一个类,后面加上自定义的类名即可。如这里定义的person类,使用class person定义了一个person类,然后在person这个类的类体里面定义person这个类应该具有的成员变量(即属性)和方法,如这里定义的int id和int age这个两个成员变量,或者叫属性,这个id表示人的身份证号码,人应该具有这个属性,age表示人的年龄,这也是人应该具有的。这样就在person这个类里面定义了两个人应该有的属性,接下来就是定义方法了,这里定义了三个方法,分别是getAge()、setAge(int i)和getId(),分别用来获取人的年龄,设置人的年龄,获取人的id,getAge()方法获取了人的年龄后,将获取到的值返回,所以使用了return age语句,getId()方法也使用了return id语句用于返回获取到的id的值。
之前也说过,类是一个对象的抽象,简单的说,类就是一种对象的概括,一个大类!就好像这里定义的person类,是人特征的一个概括,你可以根据这个的类的方法属性去new一个具体特征的人,而这个人就是对象!
二. 成员变量
在JAVA里面的任何变量首先应该要声明,然后再赋值,然后再使用。成员变量和局部变量有一个重要区别:成员变量在类里面声明时如果不进行初始化,那么JAVA会默认给它初始化,而局部变量JAVA不会默认给它初始化,所以在方法里面声明一个局部变量如果不给它初始化时就会出错。默认初始化大多数都是0,boolean类型的为false,引用类型的为null,如过不记得JAVA对成员变量默认的初始化是多少的话,那就这样做,定义一个成员变量,不给它初始化,然后直接打印这个成员变量,打印出来的结果就是JAVA默认的初始化的值。
这里就有个问题了!为什么成员变量在声明的时候不进行初始化,JAVA会默认给他初始化,而局部变量不会呢?而且为什么局部变量不给它初始化就会报错呢?
首先从设计者的角度出发,当我们新建一个对象时,Java会在Heap中申请一块内存区域用以存放类的数据。而成员变量就是类的数据,也是放在这块内存区域中的。只需要JVM在申请内存的时候顺便把整块区域都置为零即可完成初始化,方便快捷。而对于方法的局部变量,是在线程的Stack中,当然Stack他也可以帮我们初始化,不过有一个问题。对于有些局部变量,在方法的一开始是没有的,有些在循环中的局部变量是要反复的声明多次的。有些局部变量作用域结束后,另一个局部变量又会占用这个局部变量的位置。那么初始化要放在何时呢?当然JVM可以帮我们初始化多次,不过那样或许会带来性能问题,开销大!
三、Java面向对象的基本概念——引用
引用类型和基本类型有着巨大的区别,当声明一个int i=0时,系统会马上给这个i分配一个内存空间(在栈内存里面分配一小块区域用来装数字0),里面装着一个值为0,以后使用i这个名字马上就可以访问这个内存空间里面的值,这就是基本数据类型,所以基础类型就只占一块内存。基础类型之外的类型全都叫引用类型,我们定义一个Mouse m,这个m就是一个引用类型的数据。引用类型有什么重要的特征——引用类型占2块内存。我们定义好这个类之后,需要使用new关键字把这个类的对象实例化出来,也就是真真正正造出一个对象出来才能使用这个对象。
eg:int i=0; 我们可以直接使用i
Mouse m; 我们必须要m=new Mouse(); 才能使用
如何在内存中区分类和对象?
类是静态的概念,是位于代码区里面。对象是new出来的,它是位于堆内存,为什么对象要位于堆内存?因为堆内存是用来动态分配内存的,只有在运行当中才会new一个对象放堆内存里面,那这个对象到底有多大个,这个东西你不知道,你没有办法提前知道,所以你没有办法提前分配内存给这个对象,你只有在运行期间才能去分配它。什么叫运行期间?敲JAVAC这个命令那是在编译期间,编译完成后再敲JAVA命令,那就是运行期间了。只有在运行期间,才能够明白这个对象到底要分配多大的空间给它,所以把它放在堆内存里面,堆内存比较大,动态分配内存用它。如果这个对象不用了,那它就是垃圾,那么就等着垃圾收集器把它收集回去,释放掉占用的内存。
记住,以后一提到引用,脑子里马上浮现引用那就是一小块内存指向一大块内存。
四、对象的创建和使用
使用new关键字来创建一个新的对象。
五、类和对象的关系
在内存中分析类和对象的关系
假设这里有一个类C,我们定义了一个类class C,然后在这个类里面定义了两个成员变量: int i和int j。定义好了这两个成员变量以后,我们写了一个main()方法(public static void main(Strng[] args)),程序开始执行。第一句我们写了 C c1 = new C(),这句的代码是我们相当于在堆内存里创建了一个对象,同时也创建了这个对象的一个引用对象c1,c1位于栈内存中,c1这个引用对象指向堆中一大块内存,这一大块内存里面装着new出来的那个对象。这里面我们一般来说是new出来两个对象c1和c2,当然,实际上,严格来讲,c1和c2叫做对象的引用,有时候,简称new出来了两个对象,c1和c2。你脑子里马上要浮现出两块内存,c1指向一块,c2指向一块。局部变量是分配在栈内存里面的,main方法里面的c1和c2都是局部变量,所以在栈里面分配了两小块内存出来,一块是c1的,一块是c2的,c1这块内存里面装着一个值,或者叫装着一个地址,这个地址是什么,我们不知道,我们只知道根据这个值就能找到new出来的C这个类里面的一个对象,而在这个对象里面有它自己的成员变量i和j,里面的两小块内存是分别用来装i和j的值的,因为每一个对象都有自己不同的成员变量的值,所以c1指向的那块对内存里面又分成一小块一小块内存,每一个小块的内存都装着这个对象的成员变量(或者叫属性)。如这里的第一小块装着i的值,第二小块装着j的值,所以当我们去访问第一小块里面装着的成员变量时,我们应该这样写:c1.i,这样就拿到了i的值,c1.j,这样就拿到了j的值。同理,c2这个对象也指向了一个new出来的C这个类里面的另一个对象,这个对象也有成员变量i和j,只不过和c1指向的那个对象里的i和j的值不同而已。要访问这个这个对象的成员变量时 ,也是要c2.i,c2.j这样去访问。
六、构造方法
在面向对象里面有一个特殊的方法,叫构造方法。
构造方法是用来创建一个新的对象的,与new组合在一起用,使用new+构造方法创建一个新的对象。你new一个东西的时候,实际上你调用的是一个构造方法,构造方法就是把自己构造成一个新的对象,所以叫构造方法,构造一个新对象用的方法叫构造方法。
构造方法比较特殊,构造方法的名字必须和类的名字完全一模一样,包括大小写,并且没有返回值。如原来定义的一个person类,在类里面声明了两个成员变量id与age,这时候你可以再为这个person类定义一个它的构造方法person(int n,int i),这个方法的名字和类名完全相同,并且没有返回值,也就是在这个方法前面不能写任何的方法的返回类型修饰符,连void都不可以写。
构造方法写好后就和new组合在一起使用,new的作用是构建一个新对象,创造一个新对象,所以new的时候实际当中调用的是构造方法。只有调用了这个构造方法才能构造出一个新的对象。例如:
下面是在main方法里面调用person构造方法时的内存分析情况:
当方法调用完成之后,栈里面为它分配的空间全部都要消失,即把这个方法调用时分配给它的内存空间释放出来,所以这个构造方法person调用完成之后,栈内存里面分配的两小块内存_id和_age自动消失了。这样就把它们所占的空间让了出来,让其他的方法去占用。而new出来的对象则永远留在了堆内存里面。
声明一个类,若没有在类中指定其构造方法(构造函数)时,编译器会为这个类自动添加形如类名( ){ }的构造函数。
当没有给这个类指明构造方法时,系统会默认地给这个类加上point ( ) { }这样一个空的构造方法。所以才可以在main方法中使用
point p = new point(); 实际上你调用的就是编译器默认给它加上的point ( ) { }这个构造方法,在这个构造方法当中,默认地把类里面的成员变量x和y初始值设为0。正是因为系统给它默认加上这么一个构造方法,所以才能在main方法里面调用。但要记住一点,一旦给这个类里面指定了构造方法,那么系统就不会再给这个类添加构造方法了。
七、总结
面向对象主要是根据一个类的基本结构进行总结分析的,首先是讲了什么是类,类和对象的关系区别!然后到变量,变量分为成员变量和局部变量,这里主要介绍了基本的概念和要注意的事项以及引用的问题!然后就是构造方法了!