Изменчивость строки Java - java.lang.NoSuchFieldException: смещение
Я новичок в Java, и я увидел здесь раздел вопросов и ответов с двумя примерами, в которых устранена изменчивость. После тестирования MutableString.java:
import java.lang.reflect.Field;
public class MutableString {
public static void main(String[] args) {
String s = "Immutable";
String t = "Notreally";
mutate(s, t);
StdOut.println(t);
// strings are interned so this doesn't even print "Immutable" (!)
StdOut.println("Immutable");
}
// change the first min(|s|, |t|) characters of s to t
public static void mutate(String s, String t) {
try {
Field val = String.class.getDeclaredField("value");
Field off = String.class.getDeclaredField("offset");
val.setAccessible(true);
off.setAccessible(true);
int offset = off.getInt(s);
char[] value = (char[]) val.get(s);
for (int i = 0; i < Math.min(s.length(), t.length()); i++)
value[offset + i] = t.charAt(i);
}
catch (Exception e) { e.printStackTrace(); }
}
}
Я получил следующую ошибку:
java.lang.NoSuchFieldException: offset
Любая информация о следующем будет принята с благодарностью:
а) почему я получаю это исключение
б) как проверить, какие поля существуют в классе (в частности, строки Java)
1 ответ
Отказ от ответственности: эти виды хаков являются интересными уроками в обучении и забавных мелочах. Но они определенно не то, что вы хотите использовать в любом рабочем коде. Это приведет к боли.
По своей природе такой взлом всегда зависит от деталей реализации взломанных классов.
В вашем случае вы, кажется, используете String
реализация, которая не имеет offset
поле, но использует какой-то другой механизм (или, может быть, просто другое имя!).
Например, я только что рассмотрел класс Oracle Java 7 String, и у него больше нет offset
поле (которое использовалось в Java 6 и ранее, чтобы поделиться char[]
среди подстрок)! *
Ты можешь использовать Class.getDeclaredFields()
чтобы проверить, какие поля эта реализация определяет:
for (Field f : String.class.getDeclaredFields()) {
System.out.println(f);
}
Для версии этого хака, которая работает с Java 7, вы можете сделать это:
public static void mutate(String s, String t) {
try {
Field val = String.class.getDeclaredField("value");
val.setAccessible(true);
char[] value = (char[]) val.get(s);
for (int i = 0; i < Math.min(s.length(), t.length()); i++)
value[i] = t.charAt(i);
}
catch (Exception e) { e.printStackTrace(); }
}
Конечно, это тоже сломается, если внутренности String
изменить снова.
* Вот электронное письмо, в котором говорится об этом изменении, похоже, что обмен char[]
привести к улучшению производительности только в нескольких особых случаях.