Java 如何使对象属于字符串中指定的类?
我有一个运行在类似terraria或minecraft的系统上的游戏,至少在方块方面是如此 我以一种方式构建了它,其中每个块都是一个对象,并且每种类型的块都有一个特定的类(扩展了BlockObject原型) 我让游戏保存块在一个文件中,如下所示Java 如何使对象属于字符串中指定的类?,java,string,class,object,Java,String,Class,Object,我有一个运行在类似terraria或minecraft的系统上的游戏,至少在方块方面是如此 我以一种方式构建了它,其中每个块都是一个对象,并且每种类型的块都有一个特定的类(扩展了BlockObject原型) 我让游戏保存块在一个文件中,如下所示 if(blockType.equals("BlockGrass")) { blocksArray.add(new BlockGrass(...)); } else if(blockType.equals("BlockStone")) { blocksAr
if(blockType.equals("BlockGrass"))
{
blocksArray.add(new BlockGrass(...));
}
else if(blockType.equals("BlockStone"))
{
blocksArray.add(new BlockStone(...));
}
etc
BlocksArray.add(new blockType(...));
我获取要保存的对象实例的名称,并将其存储在字符串中
我开始将给定对象的信息写入一个具有类名称的字符串中(表示它是什么类型的块,例如,作为BlockGrass.java对象的块将存储为BlockGrass)。
通常,当从保存文件读取信息时,我正在读取保存文件,当它获得块的信息时,它首先将块类型保存在本地字符串中(在本例中为BlockGrass),还保存位置(x cordinate和y cordinate)。然后它将运行一系列if语句,如下所示
if(blockType.equals("BlockGrass"))
{
blocksArray.add(new BlockGrass(...));
}
else if(blockType.equals("BlockStone"))
{
blocksArray.add(new BlockStone(...));
}
etc
BlocksArray.add(new blockType(...));
现在我想让我的游戏动态变化,这样如果有人决定创建一个新的块类(修改游戏),他们就不必修改MapReader类。因此,我不希望像上面所示运行一系列if语句(每次创建一个新的块类时,必须为该块放置一个新的if语句),而是希望它生成一个与块类型同名的类的新对象。为了给你一个更好的想法,请看以下内容
if(blockType.equals("BlockGrass"))
{
blocksArray.add(new BlockGrass(...));
}
else if(blockType.equals("BlockStone"))
{
blocksArray.add(new BlockStone(...));
}
etc
BlocksArray.add(new blockType(...));
上面显示的内容不起作用的原因是,blockType是一个字符串,它包含我要使用的类的名称。不是类名
如果不使用if语句,我怎么能做这样的事情呢?这不是编译和检查的,而是指示必须做什么
// first get the class
Class<?> rawclass = Class.forName(String);
// then check an object will fit where you want it.
if (BlockObject.class.isAssignableFrom(rawclass)){
// create the object, cast it to the correct type and add it
BlockObject object = (BlockObject) rawclass.newInstance();
blockArray.add(object);
}
//首先获取类
Class rawclass=Class.forName(字符串);
//然后检查对象是否适合您想要的位置。
if(BlockObject.class.isAssignableFrom(rawclass)){
//创建对象,将其强制转换为正确的类型并添加它
BlockObject=(BlockObject)rawclass.newInstance();
blockArray.add(对象);
}
forName和newInstance方法会出现一些例外情况。您试图做的是利用BlockObject层次结构中的多态行为。因此,使用
class.forName
是一种很好的方法。在类变量上调用newInstance()
后,需要将其强制转换为BlockObject类层次结构的基类(您称之为原型)。We保证,由于实际类是扩展BlockObject,因此根据继承的定义,它是一个BlockObject。
这里有一个例子
public class GameLoader {
private List<BlockObject> blocksArray = new ArrayList<BlockObject>();
public Object getNewBlock(String blockClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class blockClass = Class.forName(blockClassName);
return blockClass.newInstance();
}
public void addNewBlockType(String typeName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
BlockObject castedType = (BlockObject)getNewBlock(typeName);
blocksArray.add(castedType);
}
}
公共类游戏加载器{
私有列表块ray=new ArrayList();
公共对象getNewBlock(字符串blockClassName)抛出ClassNotFoundException、InstanceionException、IllegaAccessException{
Class blockClass=Class.forName(blockClassName);
返回blockClass.newInstance();
}
public void addNewBlockType(String typeName)抛出ClassNotFoundException、InstanceionException、IllegaAccessException{
BlockObject castedType=(BlockObject)getNewBlock(typeName);
blocksArray.add(castedType);
}
}
在此类对象上调用的基类的任何方法都将显示多态行为。使用class.forName(String).newInstance();似乎你在发明序列化?@redge虽然这确实给了我类的实例,但我不能执行
.add(new class.forName(String.newInstance())代码>创建一个通用工厂,它接收一个应该扩展一个超类的块类型,然后你只需传递块类型引用并返回块类型的正确实例…现在我有一个问题,关于构造函数,我假设在这种情况下它没有被调用?@yoseph1998,是的,它被称为class.newInstance()创建由该类对象表示的类的新实例。该类被实例化,就好像是由一个带有空参数列表的新表达式实例化一样。
(请参阅:)。因此,如果自定义构造函数,请确保提供与默认构造函数类似的构造函数。如果需要调用具有参数的构造函数,则需要深入反射API并调用blockClass.getConstructor(…)。newInstance(…)
现在我有一个问题?将其关联到父类将删除一些功能,例如,如果块中有更多类型未知的方法,但没有BlockObject类。另外,如果未知块上的构造函数与BlockObject不同,该怎么办。