Я бы посоветовал вам просто выполнить
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); }
}
Недостатком этого является то, что это может выйти из-под контроля, если у вас есть большое количество методов, которые вы хотите завершить.