Используйте полиморфизм Java для нового соответствующего объекта (StringBuffer или StringBuilder) - PullRequest
0 голосов
/ 06 августа 2020

На самом деле, я хочу использовать полиморфизм JAVA для разработки функции, которая может возвращать StringBuffer или StringBuilder для меня, в зависимости от другого сценария. Мой код ошибки:

public class Builder{
    private boolean threadSafe;
    public Builder(boolean threadSafe) {
        this.threadSafe = threadSafe;
}
    public String buildMsg(String name, int age) {
       AbstractStringBuilder asb;
       asb = threadSafe ? new StringBuffer() : new StringBuilder();
       return asb.append("name: ").append(name).append(", age: ").append(age).toString();
}
}

Код не может быть скомпилирован. Сообщение об ошибке: «java .lang.AbstractStringBuilder» не публикуется c в «java .lang». Невозможно получить доступ из внешнего пакета. Поэтому я пробую другой метод, использую Appendable вместо AbstractStringBuilder, он по-прежнему не работает. Пока я не напишу такой код:

public class Builder{
    private boolean threadSafe;
    public Builder(boolean threadSafe) {
        this.threadSafe = threadSafe;
}
    public String buildMsg(String name, int age) {
       if (threadSafe) {
        StringBuffer sb = new StringBuffer();
        return sb.append("name: ").append(name).append(", age: ").append(age).toString();
    } else {
        StringBuilder sb = new StringBuilder();
        return sb.append("name: ").append(name).append(", age: ").append(age).toString();
    }
}
}

Код явно избыточен. Итак, как я могу использовать полиморфизм, чтобы исправить мой код. (Мой английский sh не очень хорошо, надеюсь вы хорошо понимаете)

Ответы [ 2 ]

0 голосов
/ 06 августа 2020

Я бы посоветовал вам просто выполнить

public String buildMsg(String name, int age) {
    StringBuilder sb = new StringBuilder();
    sb = sb
        .append("name: ")
        .append(name)
        .append(", age: ")
        .append(age);
    return sb.toString();
}

, поскольку в этом коде нет проблем с многопоточностью. Также это именно то, для чего предназначен класс StringBuilder.

Вы должны использовать StringBuffer, если несколько потоков имеют доступ к одному и тому же объекту StringBuffer, но поскольку вы создаете объект и в конце теряете ссылку на него, никакой другой поток не может получить доступ к объекту.

Однако, чтобы ответить на вопрос в заголовке. Если у вас есть два типа, которые реализуют метод Foo, но без общего интерфейса, например:

public class A {
    public Res Foo(Args args) { ... }
}

public class B {
    public Res Foo(Args args) { ... }
}

, тогда вам всегда понадобится какой-то регистр, чтобы различать guish между обеими версиями Foo. Но вы можете реализовать тип Adapter или Wrapper для обоих типов, например:

public abstract WrapperBase {
    public abstract Res Foo(Args args);

    public static WrapperBase Wrap(A a) {
        return new AWrapper(a);
    }
    public static WrapperBase Wrap(B b) {
        return new BWrapper(b);
    }
    // or
    public static WrapperBase Wrap(Object obj) {
        if (obj instanceof A) {
            return new AWrapper((A)obj);
        } else if (obj instanceof B) {
            return new AWrapper((B)obj);
        } else {
            throw new Exception("Can not be wrapped");
        }
    }
}

class AWrapper extends WrapperBase {
    private A a;
    public AWrapper(A a) { this.a = a; }

    @override
    public Res Foo(Args args) { return a.Foo(args); }
}

class BWrapper extends WrapperBase {
    private B b;
    public BWrapper(B b) { this.b = b; }

    @override
    public Res Foo(Args args) { return b.Foo(args); }
}

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

0 голосов
/ 06 августа 2020

StringBuffer - хотя и потокобезопасный - гарантируется только в том случае, если вы позволяете различным потокам смешивать вещи:

Thread1:

sb.append("a").append("b").append("\n");

Thread2:

sb.append("c").append("d").append("\n");

Может привести к:

"acb\nd\n"

Так что с StringBuffer вам может понадобиться:

sb.append("a" + "b" + "\n");

, что нелепо по очевидным причинам. Также подвержены ошибкам при нарушении, так как ошибочный sb.append(...).append(...) может go не обнаружен.

Так что предпочтительнее использовать поточно-безопасный регистратор или вашу собственную синхронизацию (возможно, с StringWriter?).

Кроме того, поскольку эти классы являются финальными, это действительно тупик.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...