Я пробовал класс Reloader, который должен перезагрузить класс с диска, когда он используется.Когда что-то всплывало, что я не совсем понял.
То, что статическая переменная CHANGED
в моем Test
не обновлялась, когда я изменял это через созданный экземпляр OtherClass
используя Reloader
Итак, вот код, который я использовал для проверки случая.
Test.java:
import java.io.IOException;
public class Test {
public static boolean CHANGED = false;
static Test obj = new Test();
static void change() {
CHANGED = true;
System.out.println(CHANGED); // [1] It is clearly changed to true.
}
public static void main(String[] args) {
System.out.println(new OtherClass().toString2());
System.out.println(CHANGED);
try {
Object foo = reload();
System.out.println(foo);
} catch (InstantiationException | IllegalAccessException | IOException e) {
e.printStackTrace();
} finally {
System.out.println(CHANGED); // [2] But here it is false again.
}
}
public static Object reload() throws InstantiationException, IllegalAccessException, IOException {
Object foo = new Reloader().loadClass("OtherClass").newInstance();
return foo;
}
}
, который вызывает Reloader, который в основномсоздает новый экземпляр класса, перезагружая изменения с диска.И еще немного магии.Откровенно «украдено» для частного использования из: Как заставить Java перезагрузить класс при создании экземпляра? .
Reloader.java:
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Reloader extends ClassLoader {
@Override
public Class<?> loadClass(String s) {
return findClass(s);
}
@Override
public Class<?> findClass(String s) {
try {
byte[] bytes = loadClassData(s);
return defineClass(s, bytes, 0, bytes.length);
} catch (IOException ioe) {
try {
return super.loadClass(s);
} catch (ClassNotFoundException ignore) {
}
ioe.printStackTrace(System.out);
return null;
}
}
private static byte[] loadClassData(String className) throws IOException {
File f = new File("bin/" + className.replaceAll("\\.", "/") + ".class");
int size = (int) f.length();
byte buff[] = new byte[size];
try (FileInputStream fis = new FileInputStream(f)) {
try (DataInputStream dis = new DataInputStream(fis)) {
dis.readFully(buff);
}
}
return buff;
}
}
OtherClass.java
public class OtherClass {
@Override
public String toString() {
Test.change();
return "OtherClass";
}
public String toString2() {
return "OLD";
}
}
Итак, в файле Test.java есть 2 комментария, объясняющих, что я ожидал, но что на самом деле произошло.[1] Это изменилось на истину здесь, что и ожидалось.[2] Здесь все равно было ложно, хотя код определенно выполняется после [1], не ожидается.
Мой вопрос: почему или как значение не изменилось?Должно ли это быть из-за того, что загрузчик классов создает совершенно новый «фальшивый» новый класс Test, производный от него или что-то в этом роде?
EDIT : Забыл показать, где он был вызван.