定义和使用类
静态方法与非静态方法
静态方法
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”}。
使用函式库
作为程序员,最重要的技能之一是了解如何查找和使用现有库。 在光荣的现代时代,通常可以通过网络寻求帮助来节省大量的工作和调试。