本博文为学习【从菜鸟到高手演变】系列博客http://blog.csdn.net/zhangerqing 所作笔记。

 

一、类的创建及初始化

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

public class Person {  
    String name;  
int age;  
void eat(){}  
}

测试类中:

public class ClassTest {  
    public static void main(String[] args) {  
        Person person = new Person("egg",23);  
    }  
}

new 操作符会为我们在内存中开辟空间,person是对象名,也是引用,在栈上分配,指向由new在堆上分配的内容。我们再来分析一下这个过程:当调用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 {  
     /*非静态块*/  
    {  
        System.out.println("this is non-static block!");  
    }  
   /*静态块*/  
    static{  
        System.out.println("this is 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(int id) {  
        System.out.println("person(" + id + ")");  
    }  
}  
class Build {  
    /*静态块*/  
    static{  
        System.out.println("this is static block!");  
    }  
    /*非静态块*/  
    {  
        System.out.println("this is non-static block!");  
    }  
    Person p1 = new Person(1);//------------1-----------  
    public Build() {  
        System.out.println("this is build's block!");  
        Person p2 = new Person(2);  
    }  
    Person p3 = new Person(3);  
    public static void main(String[] args) {  
        Build b = new Build();  
    }  
}

输出:

this is static block!

this is non-static block!

person(1)

person(3)

this is build's block!

person(2)

1、先装载.class文件,创建Class对象,对静态数据(由static声明的)进行初始化,而且只进行一次初始化。

2new Build()在堆上进行空间分配。

3、执行非静态块。

4、执行所有方法外定义的变量的初始化。

5、执行构造器。

我们再来看个例子:

public class Person {  
    
    public Person(int id) {  
        System.out.println("person(" + id + ")");  
    }  
    public static void main(String[] args) {  
        Build b = new Build();  
    }  
}  
class Build {  
    /*静态块*/  
    static{  
        System.out.println("this is static block!");  
    }  
    Person p1 = new Person(1);//------------1-----------  
    /*非静态块*/  
    {  
        System.out.println("this is non-static block!");  
    } 
    public Build() {  
        System.out.println("this is build's block!");  
        Person p2 = new Person(2);  
    }  
    Person p3 = new Person(3);  
}

输出:

this is static block!

person(1)

this is non-static block!

person(3)

this is build's block!

person(2)

可以看出,非静态块与成员属性的初始化顺序决定于它们在代码中的顺序。

属性

类中的属性一般分为类属性(全局变量)、实例属性(全局变量)、局部属性(局部变量)。

类属性:前面已经说过就是那些声明为static的属性,在整个过程中只进行一次初始化,在内存中只开辟一个空间,不论在哪儿调用,值保持一致。一旦被修改,所有引用它的地方都会跟着修改。一般直接通过类名进行调用。

实例属性:实例变量是可以不进行初始化,比如一个整型的实例变量假如没有初始化,则默认值为0;而局部变量假如不赋初值语法上是通过的,但是在使用这个变量是程序就报错了。实例变量在堆和栈中都分配内存空间,在堆当中分配的是对象本身,而栈中则是对这个对象的引用。

局部属性:局部变量是在方法内部声明的变量,生命期仅在方法内,方法结束后变量就消失了;局部变量必须初始化再使用,否则会报错,也就是说,假如你在方法内定义了一个局部变量,并且没有赋值,那么你在使用这个变量的时候一定得赋值,不然就报错了。同时,局部变量可屏蔽全局变量。

方法

方法就是类的行为。

由方法头和方法体构成,方法头包括:访问控制符(如public private等)、返回类型(返回类型决定该方法在调用后产生的结果的类型)、方法名、参数列表组成。声明为void的方法,返回值为空。在特殊的情况下,我们可以为方法添加一些特殊的关键字以实现特殊的功能,如synchronizedfinalstaticabstract等等。方法方面我只想介绍两个重要的方面:重载(Overload)和重写(Override亦叫覆写)。

重载:

是指在同一个类中,具有相同的方法名,不同的参数列表的方法之间的一种机制。参数列表的不同体现在:类型不同、个数不同、顺序不同,只要满足任意一个,就可以进行方法重载。

注:通过返回值来进行方法重载是不正确的!

重写:

重写是在继承中存在的,在两个类(子类和父类之间存在的关系)中,子类重写父类的方法,方法名相同,参数也相同的一种机制。

public class B extends A {  
    public String a(String name) {  
        return "welcome to you :" + name;  
    }  
}  
class A {  
    public String a(String name){  
        return "hello:"+name;  
    }  
}

当子类继承了父类后,想对父类的方法功能进行扩展,就可以使用重写,这样做的目的就是:当你需要扩展新的功能的时候,不需要新建方法,在父类的方法中进行补充,这样一种面向对象思维的体现,不用重写同样可以达到这样的效果,但是用了重写更加符合OO思想。类似的还有一种概念,叫隐藏:当子类和父类方法名相同,参数不同时,子类隐藏父类的方法实现,这就是一种机制,一种叫法,没什么实际意义,相当于我们新建了方法,只是方法名和父类的相同,但是不是父类的方法的实现。

 

Java中不定参数调用

有的时候,我们不能确定方法的参数个数,我们可以采取这种机制(String ... value),如下面的代码:

public class B{  
    public static String a(String ... value) {  
        return "welcome to you :" + value;  
    }  
    public static void main(String[] args) {  
        System.out.println(a("egg"));  
    }  
}

打印出来的结果是:welcome to you :[Ljava.lang.String;@61de33。后面这部分信息一看就是数组的信息,所以我们继续研究,发现:当你将参数写出String ... value的形式的时候,已经默认相当于:String[] value 因此你需要在方法内部获取的数据的时候写成数组下标的形式:

public static String a(String ... value) {  
        return "welcome to you :" + value[0];  
}

正常输出:welcome to you :egg

当有多个参数时,同样用下标来取值

public class B {  
    public static String a(String... value) {  
        return "welcome to you :" + value[0] + value[1] + value[2];  
    }  
    public static void main(String[] args) {  
        System.out.println(a("egg", ":niu", ":baby!"));  
    }  
}

二、类与对象的关系

经过上面这么多的演练,我们总结下类和对象的关系:看看下面的代码:

public class B {  
    public static void main(String[] args) {  
        B b = new B();  
        A a = new A();  
    }  
}  
class A {  }

这段代码中,AB都是类,ab属于对象,他们之间是种什么关系呢?

1、类是一类具有相同属性的事物的统称,是一种抽象。

2、对象是类的具体体现,又称实例。

3、类是一种静态的概念,而对象是一种动态的机制。

本章节一轮学习结束。

(本博文为学习【从菜鸟到高手演变】系列博客http://blog.csdn.net/zhangerqing 所作笔记。感谢原作者!!!)

 

你可能感兴趣的文章

评论区

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

您好,欢迎到访网站!
  查看权限

«   2018年1月   »
1234567
891011121314
15161718192021
22232425262728
293031

最新留言