阅读过程中有任何问题,请联系egg:
邮箱:xtfggef@gmail.com 微博:http://weibo.com/xtfggef
如有转载,请说明出处:http://blog.csdn.net/zhangerqing
一、类的创建及初始化
类通常是一类事物的抽象,如人就是一个类,你、我、他是这个类的具体实例,也就是对象。在Java中我们可以通过形如:class A {}来创建一个类,我们说过Java是面向对象的语言,每个对象都应该拥有它自己的属性和方法,就拿人来说,肤色、身高等是人的属性,吃、喝、玩等都是方法,也就是说属性描绘了类的特点,而方法描述了类的功能,体现在Java的类中就像下面的代码这样:
- public class Person {
- String name;
- int age;
- void eat(){
- }
- }
在面向对象的思想中,一切物体皆对象,我们以对象为单位进行编程,将这个对象所有的属性方法包装在一起,就是封装。一般情况,我们通过类的构造器来创建类对象,构造器是一个拥有和类名同样的名字的方法,我们可以对它传递参数,进行一些初始化工作,如,当我们需要在创建对象的时候,初始化其姓名及年龄,我们可以这样来做:
- public class Person {
- String name;
- int age;
- public Person(String name,int age){
- this.name = name;
- this.age = age;
- }
- void eat(){
- }
- }
测试类中:
- public class ClassTest {
- public static void main(String[] args) {
- Person person = new Person("egg",23);
- }
- }
new 操作符会为我们在内存中开辟空间,person是对象名,也是引用,在栈上分配,指向有new在堆上分配的内容,具体的JVM内存管理,请看我的另一篇博文:JVM内存管理与垃圾回收,里面有详细的介绍,此处非重点,不去深讲。我们再来分析一下这个过程:当调用new
Person()时,编译器首先检查下原类Person中是否有Person()构造方法,此处因为有public Person(String name,int age),所以new的时候,直接调用的该方法,但是很多时候,我们并没有显示声明构造方法,此时,编译器在调用的new Person()的时候,会自动为我们的Person类添加一个无参的空Person()构造方法:Person(){},来执行类的构造过程。说到构造方法,我们来看看下面的这段代码:
- public class Person {
- public Person(int id) {
- System.out.println("person(" + id + ")");
- }
- public static void main(String[] args) {
- Build b = new Build();
- }
- }
- class Build {
- Person p1 = new Person(1);
- public Build() {
- System.out.println("this is build's block!");
- Person p2 = new Person(2);
- }
- Person p3 = new Person(3);
- }
此处我主要想说明,用构造器创建类和变量的初始化顺序,该程序输出:
person(1)
person(3)
this is build's block!
person(2)
说明:不论变量放在哪儿,都会先于任意一个方法的执行前执行,包括构造方法,而构造方法是一个类必须会执行的方法,不需要显示的进行调用。同时,不论变量在哪儿分布,只要在方法外部,就一定先于方法初始化。说到这儿,我们不得不谈一下另一个关键的知识点静态块和非静态块。二者都有很简单的声明方式,只需一对大括号{}就行,静态块的话,在前面加static关键字,我们写个小程序来看看:
- public class Person {
- /*静态块*/
- static{
- System.out.println("this is static block!");
- }
- /*非静态块*/
- {
- System.out.println("this is non-static block!");
- }
- public Person(int id) {
- System.out.println("person(" + id + ")");
- }
- public static void main(String[] args) {
- Person p1 = new Person(1);
- Person p2 = new Person(2);
- }
- }
该程序输出:
this is static block!
this is non-static block!
person(1)
this is non-static block!
person(2)
说明什么问题?观察一下:我们new了两个对象,可是静态块只执行了一次,而非静态块执行了两个,且都是在调用构造器之前。我们似乎得出了一些结论:静态块是在类的装载时执行的(装入.class文件后),且只执行一次。而非静态块是在调用构造方法之前执行的,每生成一个实例对象,就会调用一次非静态块。此处,我想引入一个很重要的知识点:static关键字。一般来说,被声明为static的变量或者方法,或者前面说的块,都属于类变量、类方法,属于类的属性信息(在方法区分配内存)。如静态块一样,其它的静态数据也具有这个特点:初始化只在类装载的时候执行一次。对于类变量和类方法,还有一个重要的特点就是,外部对象对他们的引用可以直接通过类名来调用,如下面的代码:
- public class Person {
- static int id = 10;
- }
- class Test{
- public static void main(String[] args) {
- System.out.println(Person.id);
- }
- }
除了使用new操作符,我们还有一些其它方法来创建类,如Java的反射机制,我们会有专门的博文来介绍相关的知识点。
我们总结下对象的创建过程:(含顺序)根据下面这个程序的输出:
- public class Person {
- public Person(