现在的位置: 首页 > 综合 > 正文

Java之美之类与对象(一)

2014年02月12日 ⁄ 综合 ⁄ 共 3403字 ⁄ 字号 评论关闭
对于像Java这样的纯面向对象语言,类是最基本的抽象单位,一直以来我总是希望自己能写出一篇文章,来好好的梳理下自己对类和对象的理解。今天,这个愿望似乎要实现了!不知从哪个地方写起,因为这方面设计的东西太多了,说到类,就不难想到继承、多态、封装,就不难想到作用域及生命周期,很多的东西一下子涌上心头,让我不知道该从哪儿下手。本章系Java之美[从菜鸟到高手演变]系列之类与对象,希望通过我的分析,能让读者朋友们更加牢固记住相关的知识点,掌握类与对象方面的精髓!

阅读过程中有任何问题,请联系egg:

邮箱:xtfggef@gmail.com   微博:http://weibo.com/xtfggef

如有转载,请说明出处:http://blog.csdn.net/zhangerqing

一、类的创建及初始化

类通常是一类事物的抽象,如人就是一个类,你、我、他是这个类的具体实例,也就是对象。在Java中我们可以通过形如:class A {}来创建一个类,我们说过Java是面向对象的语言,每个对象都应该拥有它自己的属性和方法,就拿人来说,肤色、身高等是人的属性,吃、喝、玩等都是方法,也就是说属性描绘了类的特点,而方法描述了类的功能,体现在Java的类中就像下面的代码这样:

[java] view
plain
copy

  1. public class Person {  
  2.       
  3.     String name;  
  4.     int age;  
  5.       
  6.     void eat(){  
  7.           
  8.     }  
  9. }  

在面向对象的思想中,一切物体皆对象,我们以对象为单位进行编程,将这个对象所有的属性方法包装在一起,就是封装。一般情况,我们通过类的构造器来创建类对象,构造器是一个拥有和类名同样的名字的方法,我们可以对它传递参数,进行一些初始化工作,如,当我们需要在创建对象的时候,初始化其姓名及年龄,我们可以这样来做:

[java] view
plain
copy

  1. public class Person {  
  2.       
  3.     String name;  
  4.     int age;  
  5.       
  6.     public Person(String name,int age){  
  7.         this.name = name;  
  8.         this.age = age;  
  9.     }  
  10.     void eat(){  
  11.           
  12.     }  
  13. }  

测试类中:

[java] view
plain
copy

  1. public class ClassTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Person person = new Person("egg",23);  
  5.     }  
  6. }  

new 操作符会为我们在内存中开辟空间,person是对象名,也是引用,在栈上分配,指向有new在堆上分配的内容,具体的JVM内存管理,请看我的另一篇博文:JVM内存管理与垃圾回收,里面有详细的介绍,此处非重点,不去深讲。我们再来分析一下这个过程:当调用new
Person()时,编译器首先检查下原类Person中是否有Person()构造方法,此处因为有public Person(String name,int age),所以new的时候,直接调用的该方法,但是很多时候,我们并没有显示声明构造方法,此时,编译器在调用的new Person()的时候,会自动为我们的Person类添加一个无参的空Person()构造方法:Person(){},来执行类的构造过程。说到构造方法,我们来看看下面的这段代码:

[java] view
plain
copy

  1. public class Person {  
  2.   
  3.     public Person(int id) {  
  4.         System.out.println("person(" + id + ")");  
  5.     }  
  6.   
  7.     public static void main(String[] args) {  
  8.         Build b = new Build();  
  9.     }  
  10. }  
  11.   
  12. class Build {  
  13.     Person p1 = new Person(1);  
  14.   
  15.     public Build() {  
  16.         System.out.println("this is build's block!");  
  17.         Person p2 = new Person(2);  
  18.     }  
  19.   
  20.     Person p3 = new Person(3);  
  21.   
  22. }  

此处我主要想说明,用构造器创建类和变量的初始化顺序,该程序输出:

person(1)
person(3)
this is build's block!
person(2)

说明:不论变量放在哪儿,都会先于任意一个方法的执行前执行,包括构造方法,而构造方法是一个类必须会执行的方法,不需要显示的进行调用。同时,不论变量在哪儿分布,只要在方法外部,就一定先于方法初始化。说到这儿,我们不得不谈一下另一个关键的知识点静态块和非静态块。二者都有很简单的声明方式,只需一对大括号{}就行,静态块的话,在前面加static关键字,我们写个小程序来看看:

[java] view
plain
copy

  1. public class Person {  
  2.   
  3.     /*静态块*/  
  4.     static{  
  5.         System.out.println("this is static block!");  
  6.     }  
  7.     /*非静态块*/  
  8.     {  
  9.         System.out.println("this is non-static block!");  
  10.     }  
  11.     public Person(int id) {  
  12.         System.out.println("person(" + id + ")");  
  13.     }  
  14.     public static void main(String[] args) {  
  15.         Person p1 = new Person(1);  
  16.         Person p2 = new Person(2);  
  17.     }  
  18. }  

该程序输出:

this is static block!
this is non-static block!
person(1)
this is non-static block!
person(2)

说明什么问题?观察一下:我们new了两个对象,可是静态块只执行了一次,而非静态块执行了两个,且都是在调用构造器之前。我们似乎得出了一些结论:静态块是在类的装载时执行的(装入.class文件后),且只执行一次。而非静态块是在调用构造方法之前执行的,每生成一个实例对象,就会调用一次非静态块。此处,我想引入一个很重要的知识点:static关键字。一般来说,被声明为static的变量或者方法,或者前面说的块,都属于类变量、类方法,属于类的属性信息(在方法区分配内存)。如静态块一样,其它的静态数据也具有这个特点:初始化只在类装载的时候执行一次。对于类变量和类方法,还有一个重要的特点就是,外部对象对他们的引用可以直接通过类名来调用,如下面的代码:

[java] view
plain
copy

  1. public class Person {  
  2.     static int id = 10;  
  3. }  
  4.   
  5. class Test{  
  6.     public static void main(String[] args) {  
  7.         System.out.println(Person.id);  
  8.     }  
  9. }  

除了使用new操作符,我们还有一些其它方法来创建类,如Java的反射机制,我们会有专门的博文来介绍相关的知识点。

我们总结下对象的创建过程:(含顺序)根据下面这个程序的输出:

[java] view
plain
copy

  1. public class Person {  
  2.       
  3.     public Person(

抱歉!评论已关闭.