Java创建类和方法, since 2021-11-13

(2021.11.13 Sat)

定义类

通过关键字class和名称定义类

class DemoClass {
    // class body
}

类的继承使用extends关键字。

class ChildClass extends DemoClass {
    // class body
}

ChildClass继承了DemoClass
注意,Java中的类都默认是从Object类派生而来,Object是所有Java类的超类,于是有

class DemoClass extends Object {
    // class body
}

定义类变量、实例变量和局部变量

类变量

类变量适用于整个类,而不是类的各个对象;适用于同一个类的不同对象间共享信息或记录类级信息。用关键字static声明变量。

static int SUM;
static final int MAX_O = 0;

习惯上Java类变量名用大写,以便与其他变量区分,但并非必须。

定义实例变量

实例变量的声明和定义与局部变量几乎相同,区别在于实例变量位于类定义中。

在方法定义外声明且没有使用关键字static的变量是实例变量。习惯上石林变量位于第一行类变量定义后声明的。

class MRobot extends Robot{
    String status;
    int speed;
}

在局部变量作用域内调用实例变量

如果局部变量和实例变量的名字相同,则在作用域内的该变量名只想局部变量。如要调用实例变量,需要使用关键字thisthis关键字用于引用当前对象(实例)。很多情况下,不需要显式的使用this,因为是默认的。例如,可以只使用变量名称来引用当前类中定义的实例变量和方法的调用。由于this是指向当前实例的引用,因此只能在实例方法中的定义体内使用它。在类方法(用关键字static声明的方法)中,不能使用this关键字。

class ScopeTest{
    int iv = 100; // 定义一个实例变量
    
    void printTest(){
        int iv = 900; // 局部变量
        System.out.print('local var: ' + iv);
        System.out.print('instance var: ' + this.iv); //调用实例变量
    }
    public static void main(String[] arguments){
        // stuff
    }
}

避免出现这种情况的最好方法是,了解类定义中的所有变量,避免使用重名的局部变量。

Java中引用变量时,从最里面的作用域向外查找其定义。

定义方法

方法含四个部分

  • 方法名
  • 返回的对象类型或基本数据类型
  • 参数列表
  • 方法体

其中的方法明和参数列表构成了方法的特征标。返回的类型可以是数据类型,也可以是类。如果返回类型为void,则该方法不返回任何值。如果类型不返回void,则方法中需要用关键字return显示的返回值。

同一个类中包含多个名称相同,但是特征标不同的方法,叫做方法重载

参数传递

参数传递给方法时,对象是按引用传递,也就是在方法中对该对象所作的任何操作都将影响原来的对象。这样的对象包括数组和数组的对象,而基本数据类型和字符串是按值传递,因此在方法中无法修改原来的值。

类方法

类方法与实例方法的关系如同类变量与实例变量的关系。类方法可被类的任何实例使用,也可被其他类使用。与实例方法不同,调用类方法时,不需要有类的对象。比如Java库中的System类。

System.exit(0);
long now = System.currentTimeMillis();

定义类方法时,需要在方法定义前加上关键字static。如果方法名前有关键字static,则该方法是类方法。实例方法只能在对象中运行,而不能在类中运行。不同于实例方法,类方法不能被继承,因此在子类中不能覆盖超类的类方法。

main方法

main方法也是类方法,因为声明时有关键字staticmain方法的特殊性在于,它的存在使得所在类成为应用程序的入口类。一个项目中有多个Java文件和类,但只有main方法所在的类成为入口类,也就是主类。
main方法的特征标如下:

publish static void main(String[] arguments){
    //
}

各项含义:

  • public:该方法对其他类和对象也是可用的。
  • static:类方法
  • void:不返回任何值
  • String[] arguments:接受一个参数,即字符串数组。该参数用于存储命令行参数。arguments用于存储参数列表的字符串数组,可以自定义其名字。

在Java项目中,可将一个类指定为项目的主类,项目被打包成Java归档(JAR)文件后,如果该JAR文件被执行,将运行主类。

参数传递给Java应用程序
在命令行中运行下面指令

java Echo April 450 "this is a string"

其中的java是解释器名称,Echo是Java应用程序名称,其他内容是用空格隔开的传递给程序的三个参数。对于参数中含有空格的,必须用引号将其括起。

(2021.11.14 Sun)

创建同名方法/方法重载

类中有些方法会同名,名称相同的方法通过两个因素区分:

  • 参数个数
  • 参数的数据类型和对象

这两个因素都是方法特征标。使用多个名称相同但是特征标不同的方法被称作重载

注意,只要参数列表不同,Java就允许对方法进行重载。而如果仅仅是返回值的类型不同,在Java中不能通过类的编译

在下面这个例子中,Box类中的buildBox方法有多种定义,都返回Box类型本身。

import java.awt.Point;

class Box {
    int x1 = 0;
    int y1 = 0;
    int x2 = 0;
    int y2 = 0;

    Box buildBox(int x1, int y1, int x2, int y2) {
        this.x1 = x1; // 局部变量和实例变量同名,所以用this调用
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        return this;
    }
    // 两个方法的返回值都是Box类
    Box buildBox(Point topLeft, Point bottomRight) {
        x1 = topLeft.x;
        y1 = topLeft.y;
        x2 = bottomRight.x;
        y2 = bottomRight.y;
        return this;
    }
...

上面的重载方法还可以使用更简洁的形式,

    Box buildBox(int x1, int y1, int x2, int y2) {
        // definition
    }
    Box buildBox(Point topLeft, Point bottomRight) {
        return buildBox(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
    }

构造函数

构造函数是对象被创建时调用的方法。与其他方法不同,构造函数不能被直接调用。构造函数可以重载。使用new关键字创建类的实例时,Java做了下面三件事:

  • 为对象分配内存
  • 初始化对象的实例变量:赋予初值或设置默认值(数字为0,对象为null,布尔值为false,字符值为'\0')
  • 调用类的构造函数

创建类时,如果类没有构造函数,Java将隐式的提供一个不接受任何参数的构造函数,并调用构造函数来创造其对象。

如果类包含接受一个或多个参数的构造函数,则仅当这个类有不接受任何参数的构造函数时,才能调用这样的构造函数。

基本构造函数

构造函数与常规方法相似,但有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);

调用另一个构造函数

也就是构造函数的重载,格式为

this(arg1, arg2, arg3);

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);
    }
}

覆盖方法

当调用对象的方法时,Java将在对象的类中查找方法的定义。如果没有找到,将在超类中查找;如果没有找到,将继续沿类层次结构向上查找,直到找到方法的定义为止。继承能够在子类中重复定义和使用方法,而无须复制代码。

创建覆盖现有方法的方法

要覆盖方法,只需要在子类中创建一个特征标(名称、返回值类型和参数列表)和超类相同的方法即可。

调用原来的方法

调用超类中已经实现的方法的原因如下:

  • 完全替换原来的方法定义
  • 扩展原来的方法,加入其他行为

有时候并非完全覆盖原来的方法,仅是调用后做修改。此时可使用super关键字。
格式如

super.methodName(...);

void doMethod(String a, String b) {
    // something
    super.doMethod(a, b);
    // something
}     

覆盖构造函数

调用或覆盖超类中的方法使用的指令如前面所述,使用关键字super,而构造函数没有可供调用的方法名,因此格式如下

super(arg1, arg2, ...);

Reference

1 R. Cadenhead著,袁国忠译,21天学通Java(第7版),中国工信出版集团,人民邮电出版社

你可能感兴趣的:(Java创建类和方法, since 2021-11-13)