1 定义类,创建对象
创建对象的语法:
ClassName objectRefVar = new ClassName();
类的3种组织形式:
- 将两个类放在同一个
.java
文件中
// 文件:TestSimpleCircle.java
public class TestSimpleCircle {
//…
}
class SimpleCircle {
//…
}
此文件由Java Compiler编译,生成两个类文件: TestSimpleCircle.class
和SimpleCircle.class
如果两个类放到一个文件中,那么,文件中只有一个类可以为public class
, 与此同时,文件名必须和公有类同名,例如目前的文件名为TestSimpleCircle.java
。
- 合并两个类
public class SimpleCircle {
/** Main method */
public static void main(String[] args) {
// Create a circle with radius 1
SimpleCircle circle1 = new SimpleCircle();
System.out.println("The area of the circle of radius " + circle1.radius + " is " + circle1.getArea());
// Create a circle with radius 25
SimpleCircle circle2 = new SimpleCircle(25);
System.out.println("The area of the circle of radius " + circle2.radius + " is " + circle2.getArea());
// Create a circle with radius 125
SimpleCircle circle3 = new SimpleCircle(125);
System.out.println("The area of the circle of radius " + circle3.radius + " is " + circle3.getArea());
// Modify circle radius
circle2.radius = 100;
System.out.println("The area of the circle of radius " + circle2.radius + " is " + circle2.getArea());
}
// 下面的代码其实是另一个类,class 和 花括号都省略了。
double radius;
/** Construct a circle with radius 1 */
SimpleCircle() {
radius = 1;
}
/** Construct a circle with a specified radius */
SimpleCircle(double newRadius) {
radius = newRadius;
}
/** Return the area of this circle */
double getArea() {
return radius * radius * Math.PI;
}
/** Return the perimeter of this circle */
double getPerimeter() {
return 2 * radius * Math.PI;
}
/** Set a new radius for this circle */
void setRadius(double newRadius) {
radius = newRadius;
}
}
这种写法,将两个不同名的类合并成了一个类,看起来就是一个。
如果要测试某个类,可以在类中加一个main
方法就可以测试。
- 两个类各自放在不同的文件中
不包含main
的class将它的所有方法定义为public
, 以便其他类调用。
2 构造函数
创建对象时,使用new
操作符调用构造函数。
没有参数的构造函数叫做无参构造函数(no-arg 或 no-argument constructor) 例如Circle()
。
可以定义没有构造函数的类,这种情况下,类中会隐式定义一个方法内容为空的public
无参构造函数。此构造函数称为默认构造函数,仅当类中没有显式定义构造函数时被自动提供。
3 使用引用变量访问对象
匿名对象: 创建对象,但是并不将这个对象赋给变量
new Circle();
System.out.println("Area is " + new Circle(5).getArea());
4 使用Java库中的类
5 静态变量、常量和方法
// 声明静态变量
static int numberOfObjects;
// 定义静态方法
static int getNumberObjects() {
return numberOfObjects;
}
实例方法:
- 能够调用实例方法
- 能够访问实例数据域
- 能够调用静态方法
- 能够访问静态数据域
静态方法:
- 不能 调用实例方法
- 不能 访问实例数据域
- 能够调用静态方法
- 能够访问静态数据域
因为main
方法是静态的,所以可从类直接调用。
6 可见性修饰符
Java用包(package
) 组织类,程序的第一行语句是:
package packageName;
如果定义类时,没有包语句, 那么它就在默认包(default package)里。Java 建议将类放在包中,不要放在默认包中。
可见性修饰符有3种:public
, protected
, private
。
使用可见性修饰符public
用于类、方法和数据域以表示可以从其他任何类访问他们。
如果没有使用可见性修饰符,那么,类、方法以及数据域默认可以被同一包中的任意类类访问,这称为 package-private 或 package-access。
而 private
修饰符使得方法和数据域只能从自己的类内部访问。
protected
关键字在11.4 继承中说明,这章没有。
以下是两个包,3个类,从中可以看出,使用public
, private
, 和default
情况下对访问的限制:
// Package p1
package p1;
public class C1 {
public int x;
int y;
private int z;
public void m1() {
}
void m2() {
}
private void m3() {
}
}
// Package p1
package p1;
public class C2 {
void aMethod() {
C1 o = new C1();
能访问 o.x;
能访问 o.y;
!不能访问 o.z; // 因为是private
能调用 o.m1();
能调用 o.m2();
!不能调用 o.m3(); // 因为是private
}
}
// Package P2
package p2;
public class C3 {
void aMethod() {
C1 o = new C1();
能访问 o.x;
!不能访问 o.y; // 因为是default,且不同包
!不能访问 o.z; // 因为是private
能调用 o.m1();
!不能调用 o.m2(); // 因为是default,且不同包
!不能调用 o.m3(); // 因为是private
}
}
如果一个类没有定义为public
, 那么它只能在同一个包内被访问,下面的例子,C2
可访问C1
,但是C3
不能访问C1
。
package p1;
class C1 {
...
}
package p1;
public class C2 {
能访问 C1
}
package p2;
public class C3 {
不能访问 C1;
能访问 C2;
}
如果对象被定义在自己的类内部,那么这个对象可以访问它的私有成员。
私有构造函数
例如对于Math类,因为它的所有数据域和方法都是静态的,为了阻止用户创建Math类的实例,使用私有构造函数(private constructor) , 这样用户就没法创建类的实例了。
类java.lang.Math
的构造函数定义为:
private Math() {
}
7 数据域封装
数据域封装,即指将数据域声明为private
, 同C++的概念,使得程序易于维护,防止随意修改数据域。
为了从类外部读取和更新私有的数据域,通常为私有数据域提供两个方法:getter 和setter, (getter又叫accessor, setter又叫mutator):
public returnType getPropertyName() // getter
如果returnType为boolean
,那么getter方法依照惯例定义成如下的形式:
public boolean isPropertyName()
public void setPropertyName(dataType propertyValue) // setter
8 传递对象给方法
实际上传递的是对象的引用。
9 由对象构成的数组
创建对象数组并初始化:
// 创建对象数组
Circle[] circleArray = new Circle[10];
// 初始化
for (int i = 0; i < circleArray.length; i++) {
circleArray[i] = new Circle();
}
对象数组实际上是引用变量的数组。
10 不可变的对象和类
如果对象创建之后,无法修改数据域,这样的对象称为不可变对象,对应的类称为不可变类。
不可变类满足以下3个条件:
1. 所有数据域私有
2. 不能有可以改变数据域的方法
3. 不能有返回数据域引用的方法
下面的例子,虽然满足前两个条件,但不满足第3个条件,因此这个类不属于不可变类:
public class Student {
private int id;
private String name;
private java.util.Date dateCreated;
public Student(int ssn, String newName) {
id = ssn;
name = newName;
dateCreated = new java.util.Date();
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public java.util.Date getDateCreated() {
return dateCreated;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student(111223333, "John");
java.util.Date dateCreated = student.getDateCreated();
dateCreated.setTime(200000); // dateCreated 域发生了改变!
}
}
11 变量作用域
声明findArea()
和 radius
的顺序可任意:
public class Circle {
public double findArea() {
return radius * radius * Math.PI;
}
private double radius = 1;
}
i
必须在j
之前声明,因为j
的初值依赖于i
:
public class F {
private int i ;
private int j = i + 1;
}
12 this
引用
this
即指向对象自身, 如果访问静态变量,使用ClassName.StaticVariable,否则用this
。
使用this
调用构造函数的一个例子:
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius; // 使用this引用类自身被隐藏的radius
}
public Circle() {
this(1.0); // 使用this调用上一个构造函数
}
...
}
[1] Introduction to java Programming 10th. Chapter 9 Objects and Classes