#java #stringbuilder #charsequence
Вопрос:
Что-то вроде этого:
MyFixedLengthStringBuilder sb = new MyFixedLengthStringBuilder(2);
sb.append("123"); // <=== throws ArrayIndexOfOutBoundsException!
Все остальное было бы точно таким же. В принципе, мне нужно StringBuilder
то, что никогда не сможет вырасти.
Я вижу, что StringBuilder
это окончательно, поэтому его нельзя продлевать. Делегирование полномочий звучит как мой единственный путь здесь. Видите ли вы какой-либо другой хак/идею/решение для моих нужд?
Комментарии:
1. @DavidLee Привет, Дэвид. Как я уже сказал в вопросе,
StringBuilder
является окончательным и не может быть продлен.2. каково ожидаемое значение, сохраненное в
sb
случае выполненияsb.append('123')
, за которым следуетsb.append('456')
3. @LoveshDongre Будет выдано исключение ArrayIndexOutOfBoundsException
4.@paladin «Просто используйте строку, она никогда не сможет расти»
String
неизменна, что означает, что она не может измениться. Поэтому любая операция с ним должна возвращать новую строку. Так что, по сути, он может вырасти до неопределенного размера.5. @паладин, ты совершенно упустил главное. ОП хочет изменить его до определенного предела. Поскольку он неизменяем, вы вообще не можете его изменить, поэтому вам придется создать новую строку. Таким образом, невозможно ограничить количество раз, когда вы создаете новую строку, если вы постоянно не проверяете длину перед этим. Ваше предложение не имеет никакого смысла.
Ответ №1:
Вы могли бы сделать что-то вроде этого. Вам все равно придется иметь несколько перегруженных методов для обработки различных значений и типов аргументов, но это не обязательно должно быть полное делегирование. Это всего лишь простой пример. Это можно было бы превратить в урок. ИЗМЕНИТЬ: Изменено для обработки большинства методов.
interface TriConsumer<T,R,S> {
public void accept(T t, R r, S s);
}
public class StringBuilderSol {
static int size = 20;
static StringBuilder sb = new StringBuilder(size);
public static void main(String[] args) {
execute(sb::append, "This is fun!");
System.out.println(sb);
execute(sb::append, "Java!");
System.out.println(sb);
execute(sb::delete, 0,3);
execute(sb::replace,0,1,"I");
execute(sb::insert, 1, " like ");
execute(sb::delete, 7,15);
System.out.println(sb);
execute(sb::append, "time to crash");
}
public static <T> void execute(Consumer<T> con,
T v) {
con.accept(v);
checkLength();
}
public static <T,R> void execute(
BiConsumer<T, R> biCon,
T index, R val) {
biCon.accept(index, val);
checkLength();
}
public static <T,R,S> void execute(
TriConsumer<T, R, S> triCon,
T index, R arg1, S arg2) {
triCon.accept(index, arg1, arg2);
checkLength();
}
public static void checkLength() {
if (sb.length() > size) {
throw new IndexOutOfBoundsException();
}
}
}
С принтами
This is fun!
This is fun!Java!
I like Java!
Exception in thread "main" java.lang.IndexOutOfBoundsException
at stackOverflow.StringBuilderSol.checkLength(StringBuilderSol.java:50)
at stackOverflow.StringBuilderSol.execute(StringBuilderSol.java:32)
at stackOverflow.StringBuilderSol.main(StringBuilderSol.java:25)
Другой вариант (но у которого есть свои проблемы) — настроить таймер для периодической проверки размера StringBuilder.
Комментарии:
1. Вы также можете объявить
Consumer<String> fnc
, так как на самом деле вы не используете возвращаемое значение.2. Я изменил это, чтобы использовать универсальные типы для гибкости. И, как сказал @izruo, вы могли бы использовать потребителей вместо функций. Для версии с тремя вариантами необходимо будет создать функциональный интерфейс.
Ответ №2:
Если бы я мог создать свой собственный класс, он выглядел бы примерно так, и в зависимости от требований можно было бы добавить больше вещей
public class MyFixedLengthStringBuilder {
StringBuilder sb;
int size;
public MyFixedLengthStringBuilder(int size) {
if(size < 0)
throw new IllegalArgumentException();
this.size = size;
sb = new StringBuilder(size);
}
public void append(String str) {
sb.append(str);
if(sb.length() > size) {
sb.setLength(size);
throw new ArrayIndexOutOfBoundsException();
}
}
}
Ответ №3:
Прежде всего, недостаточно четко определены требования заказчика: запрашивают ли они класс, совместимый с назначением StringBuilder
, или они просто запрашивают класс с определенной функциональностью?
Первое технически невозможно, так StringBuilder
как объявлено как final
, поэтому любая переменная типа StringBuilder
всегда будет иметь одинаковое поведение.
Последнее позволяет вам указать свой собственный новый класс с помощью ваших собственных методов. Что касается требования, клиент, скорее всего, указал «Мне просто нужно все от StringBuilder
.», потому что они не потрудились на самом деле проверить, что именно им нужно. Я думаю, что вполне вероятно, что вы сможете создать класс всего с несколькими методами, подходящими для потребностей клиента, если вы оба приложите некоторые усилия для сокращения требований.
И да, как вы уже упоминали, в этом случае неплохо использовать композицию с исходным StringBuilder
классом.
Поскольку вы просили взломать, теоретически вы могли бы написать свою собственную реализацию java.lang.StringBuilder
и предоставить пользовательский ClassLoader
интерфейс, который загружает вашу реализацию вместо стандартной java. Я надеюсь, что очевидно, что это не очень хорошая практика, хотя.