第五章 创建类和方法
5.1 定义类
默认情况下,类将从Object派生而来,后者是Java类层次结构中所有类的超类。
关键字extends用于指定超类,如下面的Ticker的子类所示:
class SportsTicker extends Ticker{
//body of the class
}
未用extends指定超类时,超类默认为Object。
5.2 创建实例变量和类变量
5.2.1 定义实例变量
class MarsRobot extends ScienceRobot{
String status;
int speed;
float temperature;
int power;
}
5.2.2 类变量
在类中,使用关键字static来声明类变量,
static final int MAX_OBJECTS = 10;
static int SUM;
根据约定,很多Java程序员都将整个类变量名大写,以便将这种变量与其他变量区分开来。
5.3 创建方法
5.3.1 定义方法
public class RangeLister {
public static void main(String[] args) {
int[] range;
RangeLister lister = new RangeLister();
range = lister.makeRange(4, 13);
System.out.print("The array: [ ");
for (int i = 0; i < range.length; i++) {
System.out.print(range[i] + " ");
}
System.out.println("]");
}
int[] makeRange(int lower, int upper) {
int[] range = new int[(upper - lower) + 1];
for (int i = 0; i < range.length; i++) {
range[i] = lower++;
}
return range;
}
}
输出:
The array: [ 4 5 6 7 8 9 10 11 12 13 ]
5.3.2 关键字 this
有时候您可能想在方法体中引用当前对象,即其方法被调用的对象,以便将当前对象的实例变量或当前对象作为参数传递给其他方法。
t=this.x; // x是这个对象的实例变量
z.resetData(this); // 用z类中的resetData方法,
// 把当前对象传递给它
return this; //返回当前对象
5.3.3 变量作用域和方法定义
- 为了避免局部变量test隐藏实例变量test,可以使用this.test来引用实例变量,使用test来引用局部变量。
- 了解超类中定义的所有变量,并避免重新定义超类中已有的变量。
5.3.4 将参数传递给方法
public class Passer {
void toUpperCase(String[] text){
for(int i=0;i<text.length;i++){
text[i]=text[i].toUpperCase();
}
}
public static void main(String[] args){
Passer passer= new Passer();
passer.toUpperCase(args);
for(int i=0;i<args.length;i++){
System.out.print(args[i]+" ");
}
System.out.println();
}
}
5.3.5 类方法
定义类方法时,需要在方法定义前加上关键字static,就像需要在类变量前加上static一样。
static void exit(int argument){
// body of method
}
如果方法名前面没有关键字static,则该方法将是实例方法。实例方法只能在对象中运行,而不能在类中运行。
5.4 创造Java应用程序
- 要让Java应用程序能够运行,只需一个用作程序入口的类即可。要成为应用程序的入口类,只需包含main()方法即可。应用程序运行时,Java虚拟机(JVM)将调用该方法。
- 方法main()的特征标如下:
public static void main(String[] arguments){
// body of method
}
其中各项含义如下:
- public意味着该方法对其他类和对象也是可用的。方法main()必须被声明为public。
- static意味着方法main()是一个类方法
- void意味着方法main()不返回任何值
- main()接受一个参数,一个字符串数组。该参数用于存储命令行元素
助手类
只要是Java中能找到的类,程序在运行时就可以使用。然而,只有入口类需要main()方法。该方法被调用后,接下来将执行程序中使用的各种类和对象中的方法。虽然助手类可以包含main()方法,但程序运行时,它们将被忽略。
5.5 java应用程序和参数
5.5.1 将参数传递给Java应用程序
使用JDK中的java解释器时,要将参数传递给Java程序。其中Java是解释器的名称,Echo是Java应用程序的名称,其他的内容是传递给程序的参数。
java Echo Wilhelm Hough "Tim Wakefield" 49
用引号将Tim Wakefield括起后,它将被视为一个参数。
5.5.2 在Java程序中处理参数
public static void main(String[] arguments){
// body of method
}
其中,arguments是用于存储参数列表的字符串数组,可以按您的喜好给这个数组命名。
5.6 创建同名方法
当您调用不同对象的方法时,Java将对方法名和参数进行匹配,以确定执行哪个方法定义。
要创建重载方法,可在同一个类中创建多个不同的方法定义,它们的名称相同,但参数列表不同。不同之处可以是参数数目、参数类型,也可以都不同。
package com.java21days.day5;
import java.awt.Point;
public class Box {
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
public static void main(String[] args) {
Box rect = new Box();
System.out.println("Calling buildBox with " + "coordinates(25,25) and (50,50):");
rect.buildBox(25, 25, 50, 50);
rect.printBox();
System.out.println("\nCalling buildBox with " + "points(10,10) and (20,20):");
rect.buildBox(new Point(10, 10), new Point(20, 20));
rect.printBox();
System.out.println("\nCalling buildBox with " + "point(10,10),width 50 and height 50:");
rect.buildBox(new Point(10, 10), 50, 50);
rect.printBox();
}
Box buildBox(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
return this;
}
Box buildBox(Point topLeft, Point bottomRight) {
x1 = topLeft.x;
y1 = topLeft.y;
x2 = bottomRight.x;
y2 = bottomRight.y;
return this;
}
Box buildBox(Point topLeft, int w, int h) {
x1 = topLeft.x;
y1 = topLeft.y;
x2 = (x1 + w);
y2 = (y1 + h);
return this;
}
void printBox() {
System.out.print("Box: <" + x1 + ", " + y1);
System.out.println(", " + x2 + ", " + y2 + ">");
}
}
这里对new的调用是一个表达式,其值为新创建的对象。
5.7 构造函数
构造函数是对象被创建时调用的方法。与其他方法不同,构造函数不能被直接调用。使用new来创建类的实例时,Java完成下述三项操作
- 为对象分配内存
- 初始化对象的实例变量:赋予初值或设置为默认值(数字0、对象为null、布尔值为false、字符值为’\0’)。
- 调用类的构造函数。
如果类没有构造函数,Java将隐式地提供一个不接受任何参数的构造函数,并调用这个构造函数来创建对象。
5.7.1 基本的构造函数
构造函数与常规方法相似,但有3个基本区别:
- 名称总是与类相同;
- 没有返回类型;
- 不能使用return语句来返回一个值。
class MarsRobot{
String status;
int speed;
int power;
MarsRobot(String in1,int in2,int in3){
status = in1;
speed=in2;
power=in3;
}
}
可以使用下面的语句来创建这个类的对象:
MarsRobot curiosity = new MarsRobot("exploring", 5, 200);
5.7.2 调用另一个构造函数
如果构造函数的部分行为与已有构造函数相同,可在该构造函数中调用已有构造函数。
class Circle{
int x,y,radius;
Circle(int xPoint,int yPoint,int radiusLength){
this.x=xPoint;
this.y=yPoint;
this.radius=radiusLength;
}
Circle(int xPoint,int yPoint){
this(xPoint,yPoint,1);
}
}
Circle的第二个构造函数只接受圆心的x和y作为参数。由于没有定义半径,因此将使用默认值1——调用第一个构造函数,并将参数xPoint、yPoint和整数字面量1作为参数传递给它。
5.7.3 重载构造函数
package com.java21days.day5;
import java.awt.Point;
public class Box2 {
int x1=0;
int y1=0;
int x2=0;
int y2=0;
Box2(int x1,int y1,int x2,int y2){
this.x1=x1;
this.y1=y1;
this.x2=x2;
this.y2=y2;
}
Box2(Point topLeft,Point bottomRight){
this(topLeft.x,topLeft.y,bottomRight.x,bottomRight.y);
}
Box2(Point topLeft,int w,int h){
this(topLeft.x,topLeft.y,topLeft.x+w,topLeft.y+h);
}
void printBox(){
System.out.print("Box:<"+x1+","+y1);
System.out.println(" ,"+x2+" ,"+y2+">");
}
public static void main(String[] args){
Box2 rect;
System.out.println("Calling Box2 with coordinates "+"(25,25) and (50,50):");
rect= new Box2(25,25,50,50);
rect.printBox();
System.out.println("\nCalling Box2 with points "+ "(10,10) and (20,20):");
rect=new Box2(new Point(10,10),new Point(20,20));
rect.printBox();
System.out.println("\nCalling Box2 with 1 point "+"(10,10), width 50 and 50:");
rect = new Box2(new Point(10,10),50,50);
rect.printBox();
}
}
5.8 覆盖方法
在子类中定义一个特征标与超类相同的方法。这样,当该方法被调用时,将找到并执行子类的方法,而不是超类的方法。这被称为覆盖方法。
5.8.1 创建覆盖现有方法的方法
要覆盖方法,只需在子类中创建一个特征标(名称、返回值和参数列表)与超类相同的方法即可。
package com.java21days.day5;
public class Printer {
int x=0;
int y=1;
void printMe(){
System.out.println("x is "+x+", y is "+y);
System.out.println("I am an instance of the class "+ this.getClass().getName());
}
}
class SubPrinter extends Printer{
int z=3;
void printMe(){
System.out.println("x is "+x+", y is "+y+", z is "+z);
System.out.println("I am an instance of the class "+ this.getClass().getName());
}
public static void main(String[] args){
SubPrinter obj =new SubPrinter();
obj.printMe();
}
}
5.8.2 覆盖构造函数
为类定义构造函数时,您可能想修改对象的初始化方式,但不初始化类中新增的变量,而且要修改继承而来的变量的内容。为此,可以显示地调用超类的构造函数,并修改需要修改的变量。
- 要调用超类中的常规方法,可以使用super.methodname(arguments)。
对于super()的用法,:它必须是构造函数定义中的第一条语句。如果构造函数没有在第一条语句中显示的调用super(),java将自动调用不带参数的super()
- 您不必调用超类中特征标与子类的构造函数相同的构造函数,而只需要为需要初始化的值调用构造函数。
package com.java21days.day5;
import java.awt.Point;
public class NamedPoint extends Point {
String name;
NamedPoint(int x,int y, String name){
super(x,y);
this.name =name;
}
public static void main(String[] arguments){
NamedPoint np=new NamedPoint(5,5,"SmallPoint");
System.out.println("x is "+ np.x);
System.out.println("y is "+np.y);
System.out.println("Name is "+np.name);
}
}