目录
为对象定义类
类为对象定义属性和行为。使用一个通用类来定义同一类型的对象。一个对象是类的一个实例,可以从一个类中创建多个实例,创建实例的过程称为实例化。类还提供了一种称为构造方法的特殊类型的方法,调用它可以创建一个新的对象。构造方法本身可以完成任何动作的,但是设计构造方法是为了完成初始化动作,例如:初始化对象的数据域。
使用构造方法构造对象
构造方法是一种特殊的方法,它们有三个特殊性:
1、构造方法必须具备和所在类相同的名字。
2、构造方法没有返回值类型,甚至连void都没有。
3、构造方法是在创建一个对象使用new操作符时调用的。构造方法的作用是初始化对象。
构造方法也可以重载。通常,一个类会提供一个没有参数的构造方法。这样的构造方法称为无参构造方法。一个类可以不定义构造方法。在这种情况,类中隐含一个方法体为空的无参构造方法,这个构造方法称为默认构造方法,当且仅当类中没有明确定义任何构造方法时才会自动提供它。
通过引用变量访问对象
新创建的对象在内存中被分配空间,它们可以通过引用变量来访问。对象是通过引用变量来访问的。该变量包含对对象的引用,使用如下语法格式声明这样的变量:
className ojectRefVar;
本质上讲,一个类是程序员定义的类型。类是一种引用类型,这就意味着该类型的变量都可以引用该类的一个实例。下面的语句声明变量myCircle的类型是Circle类型:
Circle myCircle;
变量myCicle能够引用一个Circle对象。下面语句创建一个对象,并且将它的引用赋给变量myCircle:
myCircle = new Circle();
采用如下所示的语法,可以写一条包括声明对象引用变量、创建对象以及将对象的引用赋值给这个变量的语句。
ClassName ojectReVar = new ClassName();
变量myCircle中放的是对Circle对象的一个引用。
访问对象的数据和方法
在面向对象编程中,对象成员可以引用该对象的数据域和方法。在创建一个对象之后,它的数据和方法可以使用点操作符(.)来访问和调用。我们曾经使用Math.methodName(参数) 来调用Math类的方法。原因是Math类中的所有方法都是用关键字static定义的静态方法。但是平时我们定义的是实例方法而非静态方法。有时候,一个对象在创建之后并不需要引用则用匿名对象,例如:System.out.println("Area is " + new Circle(5).getArea() );
引用数据域和null值
引用类型数据域的默认值是null,数值类型数据域的默认值是0,boolean类型数据域的默认值是false,而char类型数据域的默认值是'\u0000'。
基本类型变量和引用类型变量的区别
每个变量都代表一个存储值的内存位置。声明一个变量时,就是告诉编译器这个变量可以存放什么类型的值。对基本类型变量来说,对应内存所存储的值是基本类型值,对引用类型变量来说,对应内存所存储的值是一个引用,是对象的存储地址。
静态变量、常量和方法
静态变量被类中的所有对象所共享。静态方法不能访问类中的实例成员。
Circle类的数据域radius称为一个实例变量。实例变量是绑定到类的某个特定实例的,它是不能被同一个类的不同对象所共享的。例如:
Circle circle1 = new Circle();
Circle circle2 = new Circle();
circle1中的radius和circle2的radius是不相关的,它们存储在不同的内存位置。circle1中的radius的变化不会影响circle2中的radius。如果想让一个类的所有实例共享数据,就要使用静态变量。静态变量将变量值存储在一个公共的内存地址,因为它是公共地址,所以如果某一个对象修改了静态变量的值,那么同一个类的所有对象都会受到影响。
使用“类名.方法名(参数)”的方式调用静态方法,使用“类名.静态变量”的方法访问静态变量。这会提高可读性,因为可以很容易识别出来类中的静态方法和数据。
实例方法可以调用实例方法和静态方法,以及访问实例数据域或者静态数据域。静态方法可以调用静态方法以及静态数据域,然而,静态方法不能调用实例方法或者访问实例数据域。
如果一个变量或方法依赖于类的某个具体实例,那就应该将它定义为实例变量或实例方法。如果一个变量或方法不依赖于类的某个具体实例,就应该将它定义为静态变量或静态方法。main方法也是静态的,可以从类中直接调用。
可见性修饰符
可见性修饰符可以用于确定一个类以及它的成员的可见性。
可以在类、方法和数据域前使用public修饰符,表示它们可以被任何其他的类访问。如果没有使用可见性修饰符,那么则默认类、方法和数据域是可以被同一个包中的任何一个类访问的。如果定义类没有声明包,就表示把它放在默认包中。java建议最好把类放入包中,而不要使用默认包。
packetage packageName;
private修饰符限定方法和数据域只能在它自己的类中被访问。
如果一个类没有被定义为公共类,那么它只能在同一个包内被访问。
修饰符private只能应用在类的成员上。修饰符public可以应用在类或类的成员上。在局部变量使用修饰符public和private都会导致编译错误。大多数情况下,构造方法应该是公共的。但是,如果防止用户创建类的实例,就该使用私有构造方法。例如:Math类的所有数据域和方法都是静态的,所以没有必要创建Math类的实例。为了防止用户从Math类创建对象,在java.lang.Math中的构造方法定义为如下所示:
private Math(){ }
数据域封装
将数据域设为私有保护数据,并且使类易于维护。
为了避免对数据域的直接修改,应该使用private修饰符将数据域声明为私有的,这称为数据域封装。在定义私有数据域的类外的对象是不能访问这个数据域的。但是经常会有客户端需要存取、修改数据域的情况。为了能够访问私有数据域,可以提供一个get方法返回数据域的值。为了能够更新一个数据域,可以提供一个set方法给数据域设置新值。get方法也称为访问器,而set方法称为修改器。
package ObjectAndClass;
public class CircleWithPrivateDataFields {
private double radius = 1;
private static int numberOfObjects = 0;
public CircleWithPrivateDataFields(){
numberOfObjects++;
}
public CircleWithPrivateDataFields(double newRadius){
radius = newRadius;
numberOfObjects++;
}
public double getRadius(){
return radius;
}
public void setRadius(double newRadius){
radius = (newRadius >= 0) ? newRadius : 0;
}
public static int getNumberOfObjects(){
return numberOfObjects;
}
public double getArea(){
return radius * radius * Math.PI;
}
}
因为这些方法是读取和修改半径的唯一途径,所以,你完全控制了如何访问radius属性。如果必须改变这些方法的实现,是不需要改变使用它们的客户程序的。这会使类更易于维护。
package ObjectAndClass;
public class TestCircleWithPrivateDataFields {
public static void main(String[] args) {
CircleWithPrivateDataFields myCircle = new CircleWithPrivateDataFields(5.0);
System.out.println("The area of the circle of radius " + myCircle.getRadius()+" is " + myCircle.getArea());
myCircle.setRadius(myCircle.getRadius() * 1.1);
System.out.println("The area of the circle of radius " + myCircle.getRadius()+" is " + myCircle.getArea());
System.out.println("The number of objects created is "+ CircleWithPrivateDataFields.getNumberOfObjects());
}
}
数据域radius被声明为私有的。私有数据只能在定义它们的类中被访问。不能在客户程序使用myCircle.radius。如果试图从客户程序访问私有数据,将会产生编译错误。
向方法传递对象参数
给方法传递一个对象,是将对象的引用传递给方法。可以将对象传递给方法。同传递数组一样,传递对象实际上是传递对象的引用。JAVA只有一种参数传递方式:值传递。下面代码展示了传递基本类型值和传递引用值的差异。
package ObjectAndClass;
public class TestPassObject {
public static void main(String[] args) {
CircleWithPrivateDataFields myCircle =new CircleWithPrivateDataFields(1);
int n = 5;
printAreas(myCircle,n);
System.out.println("\n" + "Radius is " + myCircle.getRadius());
System.out.println("n is "+ n);
}
public static void printAreas(CircleWithPrivateDataFields c,int times){
System.out.println("Radius \t\tArea ");
while(times > 1){
System.out.println(c.getRadius() + "\t\t" + c.getArea());
c.setRadius(c.getRadius() + 1);
times--;
}
}
}
对象数组
数组既可以存储基本类型值,也可以存储对象。对象的数组实际上是引用变量的数组。
不可变对象和类
可以定义不可变类来产生不可变对象。不可变对象的内容不能被改变。
通常,创建一个对象后,它的内容是允许之后改变的。有时候也需要创建一个一旦创建其内容就不能再改变的对象。我们称这种对象为不可变对象。而它的类就称为不可变类。例如:String类就是不可变的。如果一个类是不可变的,那么它的所有数据域必须都是私有的,而且没有对任何一个数据域提供公共的set方法。
变量的作用域
实例变量和静态变量的作用域是整个类,无论变量是在哪声明的。局部变量的声明和使用都在一个方法的内部。
一个类的实例变量和静态变量称为类变量或数据域。在方法内部定义的变量称为局部变量。无论在何处声明,类变量的作用域都是整个类。类的变量和方法可以在类中以任意顺序出现。
如果一个局部变量和一个类变量具有相同的名字,那么局部变量优先,而同名的类变量将被隐藏。
this引用
关键字this引用对象自身。它也可以在构建方法内部用于调用同一个类的同一个构造方法。
1、关键字this是指向调用对象本身的引用名
使用this引用隐藏数据域,this关键字可以用于引用类的隐藏数据域,例如,在数据域的set方法中,经常将数据域名用作参数名。在这种情况下,这个数据域在set方法中被隐藏。为了给它设置新值,需要在方法中引用隐藏的数据域名。
2、使用this调用构造方法