为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 ClassName 为字符串来执行“new Class”?

如何使用 ClassName 为字符串来执行“new Class”?

杨魅力 2023-07-19 10:57:31
所以我正在制作一个迷你游戏,并希望在游戏重新启动时随机获得一个新的竞技场。每个竞技场都是一个 Java 类,因为每个竞技场上的数据都会发生变化,并且当我加载和卸载地图时。正如我每次都ArrayList<String>需要做的那样。new Class它的字符串的原因是因为我不希望之前实例化该类,因为加载器位于每个地图的构造函数中我尝试过研究使用该class.forName()功能然后应用newInstance()似乎没有帮助。public class Arena {    private ArrayList<String> maps;    private Class currentMap;    public Arena() {        setMaps();        setNewMap();    }    private void setMaps() {        maps = new ArrayList<String>() {            {                add("Beach");                add("CandyLand");                add("Forest");                add("Frozen");                add("Space");            }        };    }    private void setNewMap() {        Random rand = new Random();        int n = rand.nextInt(4); // count includes 0        try {            currentMap = (Class) Class.forName(this.maps.get(n)).newInstance();        } catch (IllegalAccessException | ClassNotFoundException | InstantiationException e) {            e.printStackTrace();        }    }    public Class getCurrentMap() {        return currentMap;    }    public ArrayList<String> getMaps() {        return maps;    }}我希望得到与此相同的函数的结果new Class。只需从数组中获取类即可。
查看完整描述

2 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

Class.forName(this.maps.get(n)).newInstance()就很好了。当然,您不应该将其转换为Class,因为它们不是 的实例Class。你们的类有一个共同的基类吗?这就是要投射到的类。

您没有使用完全限定名称。也许你应该。


查看完整回答
反对 回复 2023-07-19
?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

简单的方法

我怀疑你让你的工作变得太复杂了。


switch借助Java 13 中预览的新语句功能,您可以简单地执行此操作。


int i = ThreadLocalRandom.current().nextInt( 1 , 6 ); // Half-open: origin is inclusive while the bound is exclusive.

Arena arena = switch ( i )

        {

            case 1 -> new Beach();

            case 2 -> new CandyLand();

            case 3 -> new Forest();

            case 4 -> new Frozen();

            case 5 -> new Space();

            default -> null;

        };


System.out.println( "BASIL - Done." );

只需 2 行代码(有点像)。也没有阶级和反思的争论Class

顺便说一句,你的声明:

它的字符串的原因是因为我不希望之前实例化该类,因为加载器位于每个地图的构造函数中

……对我来说毫无意义。我怀疑你是在试图避免一个不存在的问题。

艰辛的道路

不过,您询问了与 摔跤的问题Class,所以就这样吧。

我会避免使用字符串。在这里使用字符串没有任何价值。您知道将实例化的特定类集。因此List,制作一个List可以容纳Class物体的东西。我们可以随机选择这些对象之一Class来实例化该类型的对象。

定义一个包

将您的课程放入包中。我将使用一个名为 的包arena。导入该包。

import work.basil.example.arena.* ;

定义一个接口Arena

创建一个接口Arena,其中所有五个类都将实现。

package work.basil.example.arena;


public interface Arena

{

}

在每个类中实现接口

我们的五个Arena实现类中的每一个都是这样的。当我们看到控制台输出时,我们就知道构造函数运行成功。


package work.basil.example.arena;


public class Beach implements Arena

{

    public Beach ( )

    {

        System.out.println( "BASIL - Constructing Beach. " );

    }

}

制作班级列表

创建一个List包含Class对象的对象,每个对象代表游戏应用程序中使用的类。List.ofJava 9 及更高版本中的语法使此过程变得简单,生成不可修改的列表。

List < Class > classes = List.of( Beach.class , CandyLand.class , Forest.class , Frozen.class , Space.class );

从列表中随机选择一个类别

使用 随机选择一个ThreadLocalRandom::nextIntArena请注意我们如何通过使用参数化类型将所选类声明为一个< Arena >

int index = ThreadLocalRandom.current().nextInt(0 , classes.size()); // Half-open: origin is inclusive while the bound is exclusive.

Class < Arena > c = classes.get( index );

实例化,但Class::newInstance已弃用

从我们随机选择的类中实例化一个对象。

请注意,您使用的方法Class::newInstance已被弃用。Javadoc 建议使用clazz.getDeclaredConstructor().newInstance().

捕获各种可能的异常。

Arena arena = null;

try

{

    arena = c.getDeclaredConstructor().newInstance();

} catch ( InstantiationException e )

{

    e.printStackTrace();

} catch ( IllegalAccessException e )

{

    e.printStackTrace();

} catch ( InvocationTargetException e )

{

    e.printStackTrace();

} catch ( NoSuchMethodException e )

{

    e.printStackTrace();

}

发出结束信号。


System.out.println( "BASIL - Done." );


查看完整回答
反对 回复 2023-07-19
  • 2 回答
  • 0 关注
  • 134 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信