问题
I wonder why Java 5 and above provide a printf-style formatter using a static method in class String like this:
public static String format(String format, Object... args)
instead of
public String format(Object... args)
so that we can write "%02d".format(5) to get 05 instead of String.format("%02d", 5).
I imagined if I could modify the String class, I could add this:
public String format(Object... args) {
return format(this, args)
}
to get the same result.
I found that in C#, a static method is also used instead of an instance method.
I wonder why they decided to do this, but I didn't come to an explanation. The instance methods trim and substring returns a new instance of string, so they should have done the same thing with format.
Moreover, the DateFormat class also uses this:
public final String format(Date date)
for formatting dates. So if we consider the instance of DateFormat as the formatter, an instance of String could also be used as a formatter.
Any ideas?
回答1:
Perhaps "%02d".format(5) seems to imply that the object on which the format method is being called is a format string.
In this case, the format string happens to also be a String, so furthering that point, one could argue that all Strings are format strings.
Probably this can be avoided by saying that a static method in the String class can be used to format a string, rather than making some implicit statement about all Strings in general.
回答2:
While I am not a designer of Java, I can tell you one clear reason for making it static.
Java 5 came out with many features, but two of note were:
- The ability to perform "import static" commands that allowed static methods to be used from within a class easily and without listing their class name.
- A static utility method that performed printfs easily.
While it'd be nice to be able to say "bla: %d".format("foo"), by making the method static you can use format in a way that's very familiar and clean-looking to C programmers used to printf().
import static java.lang.String.format;
public class Demo {
public void Test() {
//Do some stuff
format("Hey, this is easy to read!");
}
}
And that's why! By using static imports, printfs look almost exactly like they do in C. Awesome!
回答3:
The main reason is probably that the designers of Java did not want to add too much stuff to the interface of String. Making it a member function would have meant putting it on string. Remember that a non-static method would have to be on the String object.
A second reason is that the static format maintains its resemblance to C's printf, which looks like printf(FORMAT, ARG1, ARG2...)
Another reason is that format is overloaded: there is a version that takes locale as the first parameter (before the string), so doing this on the string object would be tricky.
回答4:
"%02d".format(5) would look like "%02d" is formatted using the format 5 rather than the opposite. Also most strings are not suitable as format ("hello world".format(5)?), so the method should throw exceptions for most string objects.
回答5:
Answer rests in responsibility of Format method.
It is more logical and intuitive, at least to me, to say that "format string is input to Format method" than to say that "Format operates on format string". This is so, as we "usually" pass format string, known at design time, to Format. In contrast, for Trim, we "usually" pass variable string whose value is not known at design time.
So, making format method static, make code reading more intuitive. Look at following (C#).
answer = String.Format("This is format string : {0}", someValue);
//More readable to me
answer = "This is format string : {0}".Format(someValue);
EDIT: Even though I have used C# example code, it applies well to Java. I got -ve vote for using C# syntax!
回答6:
I really think format must be an instance method of String and so also do
- python:
2.6: print "%s" % ("Hello")3.0: print("{0}".format("Hello")) - scala:
2.7.6: println("%s".format("Hello"))
回答7:
Possibly to show that it's a "utility" function that exists for convenience, but which isn't really an intrinsic function of a String. That is, the String "%02d" is a way of representing a format, but it doesn't actually do any formatting.
The method exists for convenient formatting of Strings, but Formatter (which performs the actual formatting) can also format other types of objects (Date, etc).
回答8:
Merely because the call is reminiscent of C's sprintf function.
回答9:
Probably because String is immutable and therefore this method has to create and return a new instance of String instance. If the method was not declared static, you would probably expect it to modify the String instance on which it has been called.
回答10:
I think it is not mandatory that Java make any construct similar to anything else, even C++. Anything adopted must be so because the developers accept it. Besides, arguments like "they made it similar to something else" do not explain why they don't just make an instance method version, they do this with primitive wrappers (in addition to the instance toString() method, they have the static version).
This is what I think:
On a normal case, both forms are equivalent, but suppose that we have something like:
String invalidFormat = "%invalid"; // or something else that is invalid
and then we call:
String.format(invalidFormat, anything);
// "anything" is indeed anything....
the invalid become the argument and Java clarify this by throwing an instance of IllegalArgumentException (even in the case of Formatter, there are many kinds).
However, in something like:
invalidFormat.format(anything);
the invalid one is no longer the argument. The problem now lies with the instance it is called on and so is probaby better described as an "invalid state" (not Java's "IllegalStateException", which has a completely different usage). But because Strings are immutable, this so called "state" will never change, so it will always remain invalid as a format, even though it is a valid simple string.
Compare this with, say, java.lang.Long. Both versions of toString will never throw any exception, so they are both equivalent.
回答11:
Calling strfmt.format(objects) instead of String.format(strfmt, objects)
- is an Object Orientated call instead of a call to a static helper.
- its shorter to type.
- its simpler as it has one less argument.
- its easier to use with code completion. If you start with the format string and hit . you get the format() as an option in an IDE.
- String.format(strfmt, objects) could be accidental called as strfmt.format(text, objects) which wouldn't do what it appears to do.
回答12:
answer = String.Format("This is format string : {0}", someValue);
//More readable to me
answer = "This is format string : {0}".Format(someValue);
回答13:
Just bad design. A pythoner finds it painful.
回答14:
In C#, strings are immutable. I think that's true in Java too (not 100% sure about that). So, you are not changing the string by calling a format method on it, you are only returning a new string with the formatting. That makes it a class-level method and not an instance-level method, thus it is static. You can add an instance level facade in C# using an extension function, but that is simply syntactic sugar on top of a static function.
来源:https://stackoverflow.com/questions/792259/why-is-strings-formatobject-args-defined-as-a-static-method