【发布时间】:2011-06-26 01:36:48
【问题描述】:
在 Java 中创建静态方法以在没有任何对象实例的情况下访问它。这对我来说有点道理。但是最近我遇到了一件奇怪的事情,Java中的静态方法也可以通过它的对象实例来访问。这对我来说看起来很奇怪。有谁知道为什么这个特性是由 Java 提供的?允许使用和不使用实例访问静态方法有什么意义?
【问题讨论】:
在 Java 中创建静态方法以在没有任何对象实例的情况下访问它。这对我来说有点道理。但是最近我遇到了一件奇怪的事情,Java中的静态方法也可以通过它的对象实例来访问。这对我来说看起来很奇怪。有谁知道为什么这个特性是由 Java 提供的?允许使用和不使用实例访问静态方法有什么意义?
【问题讨论】:
它为您提供的另一个不错的(虽然有点 hack-y)功能是能够以对象的形式传递类引用。例如,假设您有以下内容:
public abstract class Animal {
public String name() { return "animal"; }
}
public class Dog extends Animal {
public String name() { return "dog"; }
}
如果您随后运行以下命令:
Animal a = new Dog();
System.out.println(a.name());
...你会得到:
dog
这实际上意味着通过实例化对象调用静态方法为 Java 提供了一种一流的函数形式。您使用抽象基类定义函数“类型”,然后通过覆盖子类中的静态方法来实例化任何适当类型的函数。然后,您可以像使用这些对象一样简单地使用相关静态方法的容器。
为了更具体,假设我们想要一个函数对字符串数组执行某种字符串编码,并且我们希望它接受一个函数作为参数,该函数对单个字符串执行编码。我们希望参数根据所需的编码而变化。没有一流的功能,这是不可能直接做到的。但是,在对象上调用静态方法为我们提供了一种解决方法:
public abstract class EncodingType {
public String encode(String s) { return s; }
}
public class Base64Encoding extends EncodingType {
public String encode(String s) { base64Encode(s); } // Assume "base64Encode" is defined
}
public class Rot13Encoding extends EncodingType {
public String encode(String s) { rot13Encode(s); } // Assume "rot13Encode" is defined
}
public class Encoder {
public String[] encodeArray(String[] s, EncodingType enc) {
for (int i = 0; i < s.length; i++) {
s[i] = enc.encode(s[i]);
}
return s;
}
}
你可以这样称呼它:
Encoder e = new Encoder();
String[] strs = { ... };
strs = e.encodeArray(strs, new Rot13Encoding());
【讨论】:
static?不?没有static的静态方法?
这样做的好处是,它允许您采用实例方法并将其转换为静态方法,而无需修改任何现有代码(类除外),从而允许向后兼容。我发现这很有用,因为我多次遇到可以设为静态的实用程序方法 - 我可以添加 static 修饰符并继续我的方式。
【讨论】:
虽然它很糟糕,但也没有令人信服的理由禁止它。
o.f();
所以我们需要在o的范围内找到一个名为f的方法。有人可能会争辩说,静态的f 当然也在o 的范围内,尽管f 实际上是为更大的范围定义的(o 的类)
【讨论】:
规范允许,但不推荐。此外,Eclipse 之类的 IDE 将对对象实例上的静态方法的访问标记为带有警告。
【讨论】:
语义相同。编译器足够聪明,可以知道您的意思(即通过类访问静态方法)。 IDE 会给你一个警告,告诉你这是不礼貌的:)
看看this question for more details。正如他们所说,这可能会产生误导,这就是 IDE 会给您警告的原因。
【讨论】: