是否可以在Java中阻止/拒绝强制转换?
我有一个简单游戏的代码,其中必须实现AgentInterface,以便为游戏中的一个角色创建代理控制器。GameState是一个实现GameStateInterface的类,实现该接口的对象可以传递给代理,因此代理可以读取和分析来自GameState的数据,并且代理必须返回角色应该执行的适当操作(返回为int) 这是代理必须实现的代理接口:是否可以在Java中阻止/拒绝强制转换?,java,casting,Java,Casting,我有一个简单游戏的代码,其中必须实现AgentInterface,以便为游戏中的一个角色创建代理控制器。GameState是一个实现GameStateInterface的类,实现该接口的对象可以传递给代理,因此代理可以读取和分析来自GameState的数据,并且代理必须返回角色应该执行的适当操作(返回为int) 这是代理必须实现的代理接口: public interface AgentInterface { // the return value specifies the direct
public interface AgentInterface {
// the return value specifies the direction of the joystick
public int action(GameStateInterface gs);
}
使用名为MyAgent的代理运行游戏:
GameState gs = new GameState();
AgentInterface agent = new MyAgent();
while (true) {
// more code here
int bestAction = agent.action(gs)
// more code here
}
但是,在游戏状态中,有些信息是代理不能访问的,因为这会欺骗控制器。但是,执行从GameStateInterface到GameState的强制转换将允许代理访问GameStateInterface中未定义的信息,如下所示:
public MyAgent implements AgentInterface {
public int action(GameStateInterface gs) {
int nLives = ((GameState) gs).nLivesRemaining; // IS IT POSSIBLE TO DENY/PREVENT THIS CAST??
// Do more stuff here
return BestAction;
}
}
GameStateInterface proxy = new GameStateProxy(gameState);
int bestAction = agent.action(proxy);
我的问题是,是否有可能阻止演员转换?我知道多态性是Java和面向对象编程语言的主要特性之一,但在这种情况下,我希望避免强制转换
我知道这可以用很多其他的方法来解决,但我很好奇是否有可能做到这一点
提前谢谢。不,没有办法做到这一点 最美好的祝愿,
费边我不知道您所描述的内容在Java中是否可行。在其他语言中,您可以重载类型转换操作符并让它们抛出异常或其他东西,但在Java中这是不可能的。你最好的办法可能是用你所说的“许多其他方式”中的一种来做。据我所知,截取类型转换并拒绝它是不可能的(比如,抛出一个ClassCastException)
但是,您可以简单地使用来控制对实际GameState对象的访问,而不是试图拒绝typecase。只需实现一个代理类,它只实现GameStateInterface,并让它将所有方法调用转发给GameState对象。现在,您不需要将实际的GameState对象引用传递给action方法,而是通过代理类的实例包装传递它。无法阻止强制转换。但是,您可以定义游戏状态,使其只能从特定位置构建。想到的一件事是实现接口的私有内部类,或者返回私有内部类实例的工厂。答案很简单,“不要在代理代码中强制转换为游戏状态”
或者,你可以将游戏状态声明为私有。或者,如果您需要从其他几个类访问它,请将其声明为受包保护。如果您担心代理正在更改游戏状态,请创建该状态的bean副本并将其传递给代理,而不是真正的GameState对象
禁止强制转换听起来不太可能(这可能是一个不可阻止的JVM语言规范特性),或者我从来没有听说过它。一般来说,您不能阻止对象在Java中强制转换。接收对
游戏状态的引用的代码将能够调用该对象上的任何非私有、非保护方法。即使你可以阻止投射,它仍然可以使用反射
如果代理
代码在您的控制之下,请保持简单,不要强制转换。如果其他人编写Agent
类,您可以创建一个代理类,该类接受GameState对象,并且只实现GameStateInterface的方法
class GameStateProxy implements GameStateInterface {
private GameStateInterface state;
public GameStateProxy(GameState state) {
this.state = state;
}
public int someMethodInGameStateInterface(int x) {
return state.someMethodInGameStateInterface(x);
}
// other methods ...
}
然后您可以创建一个代理并按如下方式传递它:
public MyAgent implements AgentInterface {
public int action(GameStateInterface gs) {
int nLives = ((GameState) gs).nLivesRemaining; // IS IT POSSIBLE TO DENY/PREVENT THIS CAST??
// Do more stuff here
return BestAction;
}
}
GameStateInterface proxy = new GameStateProxy(gameState);
int bestAction = agent.action(proxy);
接收GameStateProxy
的代码只能访问GameStateInterface
中的方法 我们要做的是提供一个带有“存根”的jar,您可以根据它进行编译,但它不包含任何实现。当实际产品运行时,我们用一个真正的jar替换存根
但在我们的例子中,我们控制它运行的位置
在我们的例子中,我们也完全按照你的要求去做。任何类都必须请求访问其他类(在运行时)。我相信这都是自定义实现,但我不确定它是否能在任何JVM上运行
您可以尝试查找/请求/任何我正在处理的东西的源代码。有一个参考实现,如果你说你有兴趣开发电缆盒,你可能能够得到它。它被称为“tru2way”或“OCAP”参考堆栈实现,我认为该项目可以在java站点的某个地方找到。可能需要一点谷歌搜索——我敢肯定你会发现这一切都是在一个特殊的类加载器或SecurityManager中完成的
编辑:我想我可能错了。我们所做的是根据被访问的类的名称,使用安全管理器创建“权限”。当线程试图调用类上的方法时,我们首先测试它的权限(我们在“受保护”类中编写代码),如果当前线程没有由类名称标识的权限,它将抛出异常
效果与您追求的效果相同,但速度较慢且更冗长。但是我们必须阻止孩子们看pr0n
编辑2:(对不起!!)
看着这样的权限描述,我相信这至少部分是可能的:
这将授予代码查询类的公共、受保护、默认(包)访问和私有字段和/或方法的权限。尽管代码可以访问私有和受保护的字段和方法名称,但它不能访问私有/受保护的字段数据,也不能调用任何私有方法。然而,恶意代码可能会使用此信息来更好地瞄准攻击。此外,它可以调用任何公共方法和/或访问类中的公共字段。如果代码通常无法调用这些方法和/或访问字段,因为它无法强制转换对象t,那么这可能是危险的
ItemReadOnly readOnly = item.getReadOnlyInstance();