Java 如何使对象属于字符串中指定的类?

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

我有一个运行在类似terraria或minecraft的系统上的游戏,至少在方块方面是如此

我以一种方式构建了它,其中每个块都是一个对象,并且每种类型的块都有一个特定的类(扩展了BlockObject原型)

我让游戏保存块在一个文件中,如下所示

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不同,该怎么办。