How to prevent an Object being cast to a String automatically
I have a class that looks like the following:
public class FileEntry {
private String name;
public FileEntry (String name) {
this.name = name;
}
}
void foo(String arg){};
foo("string" + new FileEntry("")); // How to get a compile error here
How can I make java give me a compile error instead of automatically conver开发者_如何学Cting the Object to a String?
If you have
void foo(String bar)
{
}
and you call
foo(new FileEntry());
there will be a compiler error. See here
The the toString() will be called only if you do something like
foo("this is foo" + new FileEntry());
it is impossible to do it in the compile time. in the runtime you can throw an exception from the overridden toString method
Calling toString()
is not the same as casting - you need to be aware of the difference.
You could override toString()
to not only throw an exception, but be deprecated:
@Deprecated @Override
public String toString() {
throw new IllegalStateException("toString mustn't be called on this class");
}
That will only help at compile-time if the compile-time type of the expression is FileEntry
. It will also just be a warning under most configurations.
This will also potentially confuse debuggers which try to call toString()
automatically, etc.
I can't think of any other way than to override toString()
and throw an Exception inside.
If I use this class on a method with a String argument the java compiler will automatically convert this to a String object using toString()
No, it won't. What it will do is call an overloaded method that takes an Object
parameter, if such a method exists - and such methods often call toString()
on the parameter.
There's nothing you can do to prevent overloaded methods from being used - they were put there on purpose, after all.
As others have pointed out, "str" + obj
does not involve a type cast.
It does not involve overloading either, or a call to String.concat(String)
. (Indeed, str1.concat(str2)
gives a different result to str1 + str2
when str2
is null
!)
Technically speaking, this is called a "string conversion"; see JLS 5.1.11. The conversion is equivalent to a call to String.valueOf(Object)
or a call to the static toString(primitive)
method of the relevant primitive wrapper class.
As mentioned in the comments, I don't understand what exactly is going on. But FileEntry@6e470ce1 is probably the result of the toString method of FileEntry. You can overwrite that to return whatever you want, as long as it is a String.
I am not sure why you wouldn't just implement the toString()
method in FileEntry
. If you really want a compile error, you can make a base abstract class like:
public abstract class ForceImplementToString {
@Override
public abstract String toString();
}
Then create your class like this, it will create a compile error that you have to implement the toString()
method:
public class FileEntry extends ForceImplementToString {
private String name;
public FileEntry (String name) {
this.name = name;
}
}
The Object
class has a toString()
that is inherited by every Class in Java (since very class derives from Object
). This toString()
will be called (unless it is overridden, in which case that particular object's overridden toString()
will be called).
There is nothing you can do to prevent this from happening.
On another note, what does your method look like? If you have public myMethod(String arg)
and you call myMethod(new FileEntry())
, I'm pretty sure that results in a compile-time error.
Of course, if you have an overloaded method that has Object arg
as a parameter, then that's the method that will be called. Internally, this method is probably calling toString()
on arg
. Also, using an object that is not a string in a string context (for example, if you concatenate it to a string), results in an implicit call to that object's toString()
(which can be the overridden one, or the default from from Object
).
To get a prettier result from toString()
, you should override toString()
in the FileEntry
class so that it prints something that makes more sense.
I don't think your premise is correct. Java does not automatically convert objects to strings. This code:
public class Foo {
public static void main(String[] args) {
Foo foo = new Foo();
String got = "Concatenated: ".concat(foo);
System.out.println(got);
}
public String toString() {
return "Foo object";
}
}
produces this output from my Java 1.6.0_23 compiler:
Foo.java:4: concat(java.lang.String) in java.lang.String cannot be applied to (Foo)
String got = "Concatenated: ".concat(foo);
^
1 error
You could always download the source for java, and remove toString() from Object.
精彩评论