Java之美[从菜鸟到高手演变]之类与对象(一)(二)

2014-11-24 10:51:07 · 作者: · 浏览: 1
static int id = 10;
}
class Test{
public static void main(String[] args) {
System.out.println(Person.id);
}
}
除了使用new操作符,我们还有一些其它方法来创建类,如Java的反射机制,我们会有专门的博文来介绍相关的知识点。
我们总结下对象的创建过程:(含顺序)根据下面这个程序的输出:
[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声明的)进行初始化,而且只进行一次初始化。
2、new Build()在堆上进行空间分配。
3、执行非静态块。
4、执行所有方法外定义的变量的初始化。
5、执行构造器。
我们再来看个例子:将static放在上述例子的注释1行之前,输出会有变化:
this is static block!
person(1)
this is non-static block!
person(3)
this is build's block!
person(2)
正好验证了我们上面的结论,总体来说执行顺序为:静态块->静态属性->非静态块->属性->构造器。接下来我们分析一下类的属性和方法。
属性:
类中的属性一般分为类属性(全局变量)、实例属性(全局变量)、局部属性(局部变量)。<我是这么分的,尽管有人不这么分,但是分法无所谓,理解它们的含义最重要>.
类属性:前面已经说过就是那些声明为static的属性,在整个过程中只进行一次初始化,在内存中只开辟一个空间,不论在哪儿调用,值保持一致。一旦被修改,所有引用它的地方都会跟着修改。一般直接通过类名进行调用。
实例属性:实例变量是可以不进行初始化,比如一个整型的实例变量假如没有初始化,则默认值为0;而局部变量假如不赋初值语法上是通过的,但是在使用这个变量是程序就报错了。实例变量在堆和栈中都分配内存空间,在堆当中分配的是对象本身,而栈中则是对这个对象的引用。
局部属性:局部变量是在方法内部声明的变量,生命期仅在方法内,方法结束后变量就消失了;局部变量必须初始化再使用,否则会报错,也就是说,假如你在方法内定义了一个局部变量,并且没有赋值,那么你在使用这个变量的时候一定得赋值,不然就报错了。同时,局部变量可屏蔽全局变量。
方法:
方法就是类的行为,形如:
[java]
public void say(){
dosomething;
...
}
由方法头和方法体构成,方法头包括:访问控制符(如public private等)、返回类型(返回类型决定该方法在调用后产生的结果的类型)、方法名、参数列表组成。声明为void的方法,返回值为空。在特殊的情况下,我们可以为方法添加一些特殊的关键字以实现特殊的功能,如synchronized、final、static、abstract等等。方法方面我只想介绍两个重要的方面:重载(Overload)和重写(Override亦叫覆写)。
重载:
是指在同一个类中,具有相同的方法名,不同的参数列表的方法之间的一种机制。参数列表的不同体现在:类型不同、个数不同、顺序不同,只要满足任一一个,就可以进行方法重载。
[java]
public class AreaCal {
/* 计算长方形的面积 */
public int area(int width, int height) {
return width * height;
}
/* 计算正方形的面积 */
public int area(int edge) {
return edge * edge;
}
/* 计算圆的面积 */
public double area(float radius) {
return 3.14 * radius * radius;
}
}
如例所示,同一个方法名area,同步传入不同的参数,实现不同的功能,这就是方法重载,用这样的机制有什么好处?个人感觉就是在模型上的一种统一,同样的功能,调用同样的方法,只需传入不同的参数,增强了程序的可读性和易于维护,当有很多个功能相似的方法的时候,如果我们为每个方法设计一个名称,想通过名称来区分它们的话,会很糟糕,而且会让人觉得程序的可读性差,设计不够巧妙!此处问题来了:我们可不可通过方法的返回值来区别方法重载?让我们看个例子:
[java]
public int area(int width, int height) {
return width * height;
}
public float area(int width, int height){
return width * height;
}
当其他环境调用这两个方法时,并不会先得到他们的返回值,返回值只有在方法执行完毕才返回,在调用之初,编译器无法判断他们的区别,所以只能当同名方法来处理:报错!所以试图通过返回值来进行方法重载是不正确的!
重写:
重写是在继承中存在的,在两个类(子类和父类之间