Как предотвратить автоматическое приведение объекта к строке - PullRequest
1 голос
/ 25 мая 2011

У меня есть класс, который выглядит следующим образом:

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

Как я могу заставить java выдавать мне ошибку компиляции вместо автоматического преобразования объекта в строку?

Ответы [ 11 ]

9 голосов
/ 25 мая 2011

Если у вас есть

void foo(String bar)
{

}

и вы звоните

foo(new FileEntry());

будет ошибка компилятора. Смотри здесь

toString () будет вызываться, только если вы сделаете что-то вроде

foo("this is foo" + new FileEntry());
6 голосов
/ 25 мая 2011

невозможно сделать это во время компиляции.во время выполнения вы можете выбросить исключение из переопределенного метода toString

4 голосов
/ 25 мая 2011

Вызов toString() - это , а не - это то же самое, что и кастинг - вам необходимо знать разницу.

Вы можете переопределить toString(), чтобы не только вызвать исключение, но и быть устаревшим:

@Deprecated @Override
public String toString() {
    throw new IllegalStateException("toString mustn't be called on this class");
}

Это только поможет во время компиляции, если тип выражения во время компиляции FileEntry. Это также будет просто предупреждением в большинстве конфигураций.

Это также может сбить с толку отладчиков, которые пытаются автоматически вызвать toString() и т. Д.

2 голосов
/ 25 мая 2011

Я не могу придумать другого способа, кроме как переопределить toString() и выбросить исключение внутри.

1 голос
/ 26 мая 2011

Как уже отмечали другие, "str" + obj не включает приведение типа.

Это не включает ни перегрузку, ни вызов String.concat(String).(Действительно, str1.concat(str2) дает другой результат, отличный от str1 + str2, когда str2 равен null!)

С технической точки зрения это называется "преобразованием строки";см. JLS 5.1.11 .Преобразование эквивалентно вызову String.valueOf(Object) или вызову статического метода toString(primitive) соответствующего примитивного класса-оболочки.

1 голос
/ 25 мая 2011

Если я использую этот класс в методе с аргументом String, компилятор Java автоматически преобразует его в объект String с помощью toString ()

Нет, не будет.Он будет вызывать перегруженный метод, который принимает параметр Object, если такой метод существует, и такие методы часто вызывают toString() для параметра.

Нет ничего, что можно сделать, чтобы предотвратить перегруженные методыиз-за того, что их использовали - они были помещены туда специально, в конце концов.

0 голосов
/ 27 июля 2011

Вы всегда можете загрузить исходный код для Java и удалить toString () из Object.

0 голосов
/ 25 мая 2011

Я не думаю, что ваша предпосылка верна. Java не преобразует объекты автоматически в строки. Этот код:

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";
    }
}

выводит этот вывод из моего компилятора Java 1.6.0_23:

Foo.java:4: concat(java.lang.String) in java.lang.String cannot be applied to (Foo)  
            String got = "Concatenated: ".concat(foo);
                                         ^
1 error
0 голосов
/ 25 мая 2011

Класс Object имеет toString(), который наследуется каждым классом в Java (поскольку сам класс наследуется от Object). Будет вызван этот toString() (если только он не будет переопределен, в этом случае будет вызван переопределенный конкретный объект toString()).

Вы ничего не можете сделать, чтобы этого не произошло.

С другой стороны, как выглядит ваш метод? Если у вас public myMethod(String arg) и вы звоните myMethod(new FileEntry()), я почти уверен, что это приведет к ошибке во время компиляции.

Конечно, если у вас есть перегруженный метод с Object arg в качестве параметра, то этот метод будет вызываться. Внутренне этот метод, вероятно, вызывает toString() на arg. Кроме того, использование объекта, который не является строкой в ​​строковом контексте (например, если вы связываете его со строкой), приводит к неявному вызову toString() этого объекта (который может быть переопределенным или по умолчанию из от Object).

Чтобы получить более симпатичный результат из toString(), вы должны переопределить toString() в классе FileEntry, чтобы он печатал что-то, что имеет больше смысла.

0 голосов
/ 25 мая 2011

Я не уверен, почему бы вам не реализовать метод toString() в FileEntry. Если вам действительно нужна ошибка компиляции, вы можете создать базовый абстрактный класс, например:

public abstract class ForceImplementToString {
  @Override
  public abstract String toString();
}

Затем создайте свой класс следующим образом, он создаст ошибку компиляции, которую вы должны реализовать методом toString():

public class FileEntry extends ForceImplementToString {
    private String name;
    public FileEntry (String name) {
        this.name = name;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...