对象(CS61b)

定义和使用类

静态方法与非静态方法

静态方法

Java中的所有代码都必须是类的一部分(或者类似于类的类,我们将在后面了解它)。大多数代码都是在方法内部编写的。 我们来看一个例子:

public class Dog {
    public static void makeNoise() {
        System.out.println("Bark!");
    }
}

如果我们尝试运行Dog类,我们只会收到一条错误消息:

$ java Dog
Error: Main method not found in class Dog, please define the main method as:
       public static void main(String[] args)

我们定义的Dog类没有做任何事情。 我们只是定义了Dog可以做的事情,即发声。要实际运行该类,我们需要向Dog类添加一个main方法。或者我们可以创建一个单独的DogLauncher类来运行Dog类中的方法。 例如,考虑以下程序:

public class DogLauncher {
    public static void main(String[] args) {
        Dog.makeNoise();
    }
}
$ java DogLauncher
Bark!

使用另一个类的类有时被称为该类的“客户端”,即DogLauncher是Dog的客户端。 这两种技术都不是更好:在某些情况下向Dog添加main方法可能会更好,而在其他情况下创建像DogLauncher这样的客户端类可能更好。

实例变量和对象实例化

不是所有的狗都一样。 有些狗喜欢不停地吼叫,而其他狗则声音咆哮,给所有听到光荣呼唤的人带来欢乐。 通常,我们编写程序来模仿我们所居住的宇宙的特征,并且Java的语法被精心设计以容易地允许这样的模仿。

public class TinyDog {
    public static void makeNoise() {
        System.out.println("yip yip yip yip");
    }
}

public class MalamuteDog {
    public static void makeNoise() {
        System.out.println("arooooooooooooooo!");
    }
}

正如您在过去应该看到的那样,可以实例化类,实例可以保存数据。 这导致了一种更自然的方法,我们创建Dog类的实例,并使Dog方法的行为取决于特定Dog的属性。 为了使其更具体,请考虑以下类:

public class Dog {
    public int weightInPounds;

    public void makeNoise() {
        if (weightInPounds < 10) {
            System.out.println("yipyipyip!");
        } else if (weightInPounds < 30) {
            System.out.println("bark. bark.");
        } else {
            System.out.println("woof!");
        }
    }    
}

作为使用这种狗的一个例子,考虑:

public class DogLauncher {
    public static void main(String[] args) {
        Dog d;
        d = new Dog();
        d.weightInPounds = 20;
        d.makeNoise();
    }
}

运行时,该程序将创建一只体重为20的狗,它很快会发出一声好听的“ bark. bark”。

一些重要意见和术语:

  • Java中的Object是任何类的实例。
  • Dog类有自己的变量,也称为实例变量或非静态变量。 这些必须在类中声明,不像Python或Matlab这样的语言,可以在运行时添加新变量。
  • 在Dog类中创建的方法没有static关键字。 我们称这样的方法为实例方法或非静态方法。
  • 要调用makeNoise方法,我们必须首先使用new关键字实例化Dog,然后进行特定的Dog bark。 换句话说,我们调用了d.makeNoise()而不是Dog.makeNoise()。
  • 一旦一个对象被实例化了,它可以分配给适当类型的声明变量,例如d = new Dog()。
  • 类的变量和方法也称为类的成员。
  • 使用点表示法访问类的成员。

构造函数

正如您之前所希望的那样,我们通常使用构造函数在面向对象语言中构造对象:

public class DogLauncher {
    public static void main(String[] args) {
        Dog d = new Dog(20);
        d.makeNoise();
    }
}

这里,实例化被参数化,节省了我们手动输入可能的许多实例变量赋值的时间和麻烦。 要启用这样的语法,我们只需要在Dog类中添加一个“构造函数”,如下所示:

public class Dog {
    public int weightInPounds;

    public Dog(int w) {
        weightInPounds = w;
    }

    public void makeNoise() {
        if (weightInPounds < 10) {
            System.out.println("yipyipyip!");
        } else if (weightInPounds < 30) {
            System.out.println("bark. bark.");
        } else {
            System.out.println("woof!");
        }    
    }
}

只要我们尝试使用new关键字和单个整数参数创建Dog,就会调用带有签名public Dog(int w)的构造函数。

数组实例化,对象数组

数组也使用new关键字在Java中实例化。 例如:

public class ArrayDemo {
    public static void main(String[] args) {
        /* Create an array of five integers. */
        int[] someArray = new int[5];
        someArray[0] = 3;
        someArray[1] = 4;
    }
}

类似地,我们可以用Java创建实例化对象的数组,例如:

public class DogArrayDemo {
    public static void main(String[] args) {
        /* Create an array of two dogs. */
        Dog[] dogs = new Dog[2];
        dogs[0] = new Dog(8);
        dogs[1] = new Dog(20);

        /* Yipping will result, since dogs[0] has weight 8. */
        dogs[0].makeNoise();
    }
}

请注意,new有两种不同的用法:一种是创建一个可以容纳两个Dog对象的数组,另一种是创建每个实际的Dog对象。

类方法与实例方法

Java允许我们定义两种类型的方法:

  • 类方法,又名静态方法。
  • 实例方法,又称非静态方法。

实例方法是只能由类的特定实例执行的操作。 静态方法是类本身采取的操作。 两者在不同的情况下都很有用。 作为静态方法的示例,Math类提供sqrt方法。 因为它是静态的,我们可以这样称呼它:

x = Math.sqrt(100);

如果sqrt是一个实例方法,我们将改为使用下面的笨拙语法。 幸运的是sqrt是一种静态方法,所以我们不必在真正的程序中这样做。

Math m = new Math();
x = m.sqrt(100);

有时候,拥有一个包含实例和静态方法的类是有意义的。 例如,假设想要比较两只狗的能力。 一种方法是添加一个静态方法来比较狗。

public static Dog maxDog(Dog d1, Dog d2) {
    if (d1.weightInPounds > d2.weightInPounds) {
        return d1;
    }
    return d2;
}

例如,可以通过以下方式调用此方法:

Dog d = new Dog(15);
Dog d2 = new Dog(100);
Dog.maxDog(d, d2);

观察我们使用类名调用,因为此方法是静态方法。

我们也可以将maxDog实现为非静态方法,例如:

public Dog maxDog(Dog d2) {
    if (this.weightInPounds > d2.weightInPounds) {
        return this;
    }
    return d2;
}

上面,我们使用关键字this来引用当前对象。 可以调用此方法,例如,使用:

Dog d = new Dog(15);
Dog d2 = new Dog(100);
d.maxDog(d2);

在这里,我们使用特定的实例变量调用该方法。

静态变量

对于具有静态变量的类,偶尔会有用。 这些是类本身固有的属性,而不是实例。 例如,我们可能会记录Dogs的科学名称(或binomen)是“Canis familiaris”:

public class Dog {
    public int weightInPounds;
    public static String binomen = "Canis familiaris";
    ...
}

静态变量应该使用类的名称而不是特定的实例来访问,例如,应该使用Dog.binomen,而不是d.binomen。

虽然Java在技术上允许您使用实例名称访问静态变量,但它是糟糕的样式,令人困惑,并且在我看来是Java设计者的错误。

主方法

public static void main(String[] args)

根据我们到目前为止所学到的知识,现在是时候揭开我们用于主要方法的宣言的神秘面纱。 把它分成几块,我们有:

  • public: 到目前为止,我们所有的方法都以此关键字开头
  • static: 它是一种静态方法,与任何特定实例无关。
  • void: 它没有返回类型。
  • main: 这是方法的名称。
  • String[] args: 这是传递给main方法的参数。

命令行参数

由于main是由Java解释器本身而不是另一个Java类调用的,因此提供这些参数是解释器的工作。 它们通常引用命令行参数。 例如,考虑以下程序ArgsDemo:

public class ArgsDemo {
    public static void main(String[] args) {
        System.out.println(args[0]);
    }
}

该程序打印出第0个命令行参数,例如:

$ java ArgsDemo these are command line arguments
these

在上面的例子中,args将是一个字符串数组,其中的条目是{“this”,“are”,“command”,“line”,“arguments”}。

使用函式库

作为程序员,最重要的技能之一是了解如何查找和使用现有库。 在光荣的现代时代,通常可以通过网络寻求帮助来节省大量的工作和调试。

你可能感兴趣的:(Java)