1.类、变量、方法命名遵守下列编程风格:
类:1.如果类名使用拉丁字母,那么名字的首字母使用大写,如Hello、Time等。
2.类名最好容易识别、见名知意。当类名由几个单词符合而成时,每个单词的首字母使用大写如BeijingTime、AmericanGame和HelloChina等。
变量:1.一行只声明一个变量,方便给代码增添注释内容。
如:double width; //矩形的宽double height; //矩形的高
2.变量的名字除了符合标识符规定以外,名字的首单词的首字母使用小写,从第二个单词开 始的首其他单词字母使用大写。
3.变量名字见名知意,,避免使用m1,n1等作为变量的名字,尤其名字中不要将小写的英文 字母l和数字1相邻接,很难区分。
方法:同变量。
2.方法重载
1)参数个数不同
2)参数类型不同
getArea()是一个重载方法
class Area{
float getArea(float r){
return 3.14f*r*r;
}
double getArea(float x,int y){
return x*y;
}
float getArea(int x,float y){
return x*y;
}
double getArea(float x,float y,float z){
return (x*x+y*y+z*z)*2.0;
}
}
注:方法的返回类型和参数名字不作比较。意为,如果两个方法的名字相同,即使类型不同,也必须保证参数不同。
3.对象的引用和实体
Java的对象在堆(heap,队列优先,先进先出)中分配内存,对象的引用是在栈(stack,先进后出)中分配内存。
也就是说,当用户创建一个对象时,类中的成员变量在堆中分配内存空间,这些内存空间称为该对象的实体或对象的变量,
而对象中存放着引用,该引用在栈中分配内存,以确保实体由该对象操作使用。
假如分别使用类的构造方法Point(int x,int y)创建两个对象p1和p2
Point p1=new Point(12,16);
Point p2=new Point(6,18);
那么内存模型如下图所示:
图3.1 对象内存模型
假如在程序中使用了如下赋值语句:
p1=p2;
即把p2的引用(p2在内存中的名字)赋给p1,因此p1和p2在本质上是一样的。虽然在源程序中p1和p2是两个名字,但在
系统看来它们是一个名字0xDD。系统将取消原来分配给p1的内存,这时,如果输出p1.x,结果为6,因为此时p1和p2有相同的实体。
内存模型变成如图2
图3.2 p1=p2后的对象内存模型
一个类创建的两个对象,如果具有相同的引用,那么就具有完全相同的实体。没有实体的对象称为空对象,空对象不能使用,即不能
让一个空对象去调用方法产生行为。
4.引用类型参数的传值
当参数是引用类型时,“传值”传递的是变量中存放的“引用”,而不是变量所引用的实体。
对于两个同类型的引用型变量,如果具有同样的引用,就会用同样的实体,因此,如果改变参数变量所引用的实体,就会导致原变
量的实体发生同样的变化,但是,改变参数中存在的“引用”,不会影响向其传值的变量中存放的“引用”,反之亦然。如图4.1。
图4.1 引用类型参数的传值
下面将举例说明,此例中涉及引用类型参数,含Circle类负责创建“圆”对象、Circular类负责创建“圆锥”对象
MainClass类是主类
Circle.java
public class Circle {
double radius;
Circle(double r){
radius=r;
}
double getRadius() {
return radius;
}
void setRadius(double r) {
radius = r;
}
double getArea(){
return 3.14*radius*radius;
}
}
Circular.java
public class Circular {
Circle bottom;
double height;
Circular(Circle c,double h){ //构造方法,将Circle类的实例的引用传递给bottom
bottom=c;
height=h;
}
double getVolme(){
return bottom.getArea()*height/3;
}
double getBottomRadius(){
return bottom.getRadius();
}
public void setBottomRadius(double r){
bottom.setRadius(r);
}
}
MainClass.java
public class MainClass {
public static void main(String[] args) {
Circle circle=new Circle(10); //代码1
System.out.println("main方法中circle的引用"+circle);
System.out.println("main方法中circle的半径"+circle.getRadius());
Circular circular=new Circular(circle,20); //代码2
System.out.println("circular圆锥的bottom的引用:"+circular.bottom);
System.out.println("圆锥的bottom的半径"+circular.getBottomRadius());
System.out.println("圆锥的体积:"+circular.getVolme());
double r=1;
System.out.println("圆锥更改底圆bottom的半径"+r);
circular.setBottomRadius(r); //代码3
System.out.println("圆锥的bottom的半径"+circular.getBottomRadius());
System.out.println("圆锥的体积"+circular.getVolme());
System.out.println("main方法中circle的半径:"+circle.getRadius());
System.out.println("main方法中circle的引用将发生变化");
circle=new Circle(100); //代码4 重新创建circle
System.out.println("现在main方法中circle的引用:"+circle);
System.out.println("main方法中circle的半径:"+circle.getRadius());
System.out.println("circular圆锥的bottom的引用不影响");
System.out.println("circular圆锥的bottom的引用:"+circular.bottom);
System.out.println("圆锥的bottom的半径:"+circular.getBottomRadius());
}
}
运行结果截图:
解释代码1~代码4
1.执行代码1后内存中的对象模型
Circle circle=new Circle(10);
执行此行代码后,内存中产生了一个新的circle对象,内存中的对象的模型如下图所示:
图4.2 执行代码1后的内存中的对象模型
2.执行代码2后的对象内存模型
执行代码2:
Circular circular=new Circular(circle,20);
内存中又产生了一个circular对象,并将circle对象的引用以“传值”方式传给circular的bottom,因此,circular对象的bottom和circle对象就有相同的实体radius
此时内存中的对象模型为:
图4.3 执行代码2后的内存中的对象模型
3.执行代码3后的对象内存模型
对于两个同类型的引用型变量,如果有相同的引用,就会有相同的实体,所以改变参数变量所引用的实体,就会导致原变量的实体发生同样的变化
执行代码3:
circular.setBottomRadius(r);
使得circle和circular的bottom的实体(radius)发生了同样的变化,如图:
图4.4 执行代码3后的内存中的对象模型
4.执行代码4后的对象内存模型
执行代码4;
circle=new Circle(100);
使得circle的引用发生了变化,重新创建了circle对象,即circle对象将获得新的实体(circle对象的radius=1),但circle先前的实体不被释放,因为这些实体还是
circular的bottom的实体。最初circle对象的引用是以“传值”方式传递给circular的bottom的,所以circle的引用发生变化并不影响circular的bottom的引用
(bottom对象的radius值仍然为1)。对象的模型如图:
图4.5 执行代码4后的内存中的对象模型
总结自 《Java面向对象程序设计》第二版 耿祥义 张月平 编著
第四章 类与对象