【发布时间】:2013-11-12 06:04:30
【问题描述】:
假设我有两个班级:
AnimalPen.java
public class AnimalPen {
private ArrayList<Animal> animals;
public AnimalPen() {
animals = new ArrayList<Animal>();
animals.add(new Dog("Freddy"));
animals.add(new Dog("Doggy"));
for (Animal a : animals) {
animal.makeSound();
}
}
}
Dog.java
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println("Woof");
}
}
是否有任何可能的方法可以使用反射来更改狗中的makeSound() 所做的事情,而无需修改这些类中的任何一个?例如(这只是一个建议。我对反射没有最好的理解)我创建了一个名为Dog 的类,它扩展了Animal,然后在运行时将上面发布的Dog.java 与我创建的交换这样每次调用new Dog() 时,它都会创建我的Dog 的一个新实例,而不是上面写的那个。我需要这种方式,这样我就不需要知道何时创建 Dog 的新实例,但他们使用的是我使用修改后的makeSound() 创建的类,而不是只打印出“Woof”的类”。
举一个更好的例子,作为一个实验,我试图在不修改服务器本身源代码的情况下修改 Minecraft 服务器。我正在通过CraftBukkit 将我的代码加载到 JVM 中,并且我想通过修改实体类中的方法然后将它们加载到服务器中来直接更改实体的行为方式。我知道这可以通过反射来实现,我只是或多或少想知道是否可以在运行时将整个类“交换”为它的修改版本。
【问题讨论】:
-
听起来您对策略模式很感兴趣。 en.wikipedia.org/wiki/Strategy_pattern 可能是工厂模式。你的解释很不清楚,解释一下你想达到什么情况,而不是试图解释一个半途而废的解决方案。
-
AOP 和 Java 代理之类的东西可能会让您这样做,但也许无需反射或这些(复杂的)概念就可以满足您的实际需求。您能否谈谈您希望满足的真实场景,也许我们可以帮助您确定一种直截了当的方法?
-
@MarkElliot 我更新了一个我想要完成的例子。现在我意识到了,我一直试图通过举一个复杂的例子来问一个简单的问题
-
我认为通过反射来做你想做的事情是不可行的。改变方法体不是反射可以做的事情。它也不能调整呼叫站点地址。
-
你能创建自己的类来作为原始 Minecraft 类的适配器吗?将您不想拦截的调用定向到实际类,并为要拦截的调用提供自己的方法。我不知道 MC 设置是如何工作的,所以我只是提供选项。
标签: java oop reflection runtime overriding