【问题标题】:Print a method with the help of object(which is dynamically created at run time in java)在对象的帮助下打印一个方法(在java中运行时动态创建)
【发布时间】:2018-10-27 10:20:50
【问题描述】:
  1. 为了让我的问题变得简单,我给出了一个简单的场景示例 我有一个class A,它有方法add()
  2. 现在我想在运行时 create its object dynamically 只是 提供其class name. 我该怎么做,我已经写了 以下代码,但当然它不起作用。

     public class Practice{
     public void add(){
     System.out.println("add method");
    
     }
        public static void main(String[] args) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
    
            String className = "A";
            Object xyz = Class.forName(className).newInstance();
            xyz.add();
            }}
    

上面的代码不工作,我不知道为什么,我找不到哪里出错了,second thingma​​in mathod 我正在 定义对象变量(在上面的代码中是 xyz)**,我也想 c动态地创建对象变量**。

我上面的代码给我以下错误是

  Exception in thread "main" java.lang.ClassNotFoundException: Practice
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at practice.Practice.main(Practice.java:94)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

【问题讨论】:

  • 请定义“不工作”。您是否收到任何编译错误、运行时异常或不正确的输出?使用edit 选项来澄清您的问题。
  • 我在这里看不到 swing 元素。
  • 在旁注中,public void add{ 应该是 public void add(){
  • 您提供的 Stacktrace 与您发布的代码不匹配。无论如何,我怀疑您忘记包含有关包裹的信息,所以应该是 forName("A") 而不是 forName("full.package.name.of.A")
  • @shaunTait 尝试使您的示例尽可能简单是正确的选择,恭喜!但同样重要的是(1)注意不要包含与实际问题无关的问题(不要浪费愿意帮助你的人的时间,这也会指出那些不相关的问题)(2)确保示例可以实际上用来重现你的问题。这些文章应该对您未来的问题有所帮助:minimal reproducible example(又名SSCCE

标签: java object dynamic runtime


【解决方案1】:

抛出的ClassNotFoundException 表示类加载器找不到给定名称的类。但是,这并不意味着该类在项目中不存在。字符串与完整的类名不匹配的可能性很高。

类名不仅包括具体名称,还包括包。

假设我们有一个类

package foo.bar;

public class Test
{
  public void shout() 
  {
    System.out.println( "Hello World" );
  }
}

相应的类名也是一个字符串:"foo.bar.Test" 而不仅仅是"Test"


此外,当您使用 Reflection 实例化一个对象时,返回的类型是 Object 并且您将其存储为一个,但这样做您无法访问该类的方法:

String clazzname = "foo.bar.Test";
try
{
  Object obj = Class.forName( clazzname ).newInstance();
  //compiler error because java.lang.Object does not contain a method shout()
  obj.shout();
}

但是由于我们确定返回的 Object 至少是它自己的一个实例,我们应该能够安全地将它转换为所需的对象:

String clazzname = "foo.bar.Test";
try
{
  foo.bar.Test obj = (foo.bar.Test)Class.forName( clazzname ).newInstance();
  // does work now since obj is now treated as a 'Test' object.
  obj.shout();
}

我想动态创建对象变量

不幸的是,这是不可能的,因此您必须以另一种方式跟踪您的实例,例如通过将它们存储在数组或列表或任何其他类型的集合中。

【讨论】:

  • 哇,你成就了我的一天,为什么你在编程方面如此完美而我却不是?
【解决方案2】:

尝试关注。

public class A implements Foo
{
  public void add(){
    System.out.println("add method");

    }
}

接口 Foo 定义类 A 中的方法。

 public interface Foo
    {
      void add();
    }

怎么称呼它。

public class test
{
  public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException
  {
    String className = "A";
    Foo xyz = (Foo) Class.forName(className).newInstance();
    xyz.add();
  }
}

【讨论】:

  • 为什么我们需要接口 Foo,我们可以没有它吗?
  • 因为我们不知道A类中提供的方法,所以使用接口解决了这个问题。
【解决方案3】:

您有多种选择,具体取决于您的用例:

  • 当您有多个具有相同方法的类时,只需创建一个包含该方法的interface 并让所有其他类实现该接口。

  • 当你还有动态方法时,可以使用reflection


对于第一种情况,您可以创建一个接口,在我的情况下为Addable

public interface Addable{
    void add();
}

然后让所有可能动态创建的类实现该接口:

public class A implements Addable {
    public void add(){
        // logic
    }
}

public class B implements Addable {
    public void add(){
        // other logic
    }
}

在您的主要方法中,您可以从以下位置更改代码行:

Object xyz = Class.forName(className).newInstance();

收件人:

Addable xyz = (Addable) Class.forName(className).newInstance();

对于第二种有反射的情况:

public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
     String className = "A";
     String methodName = "add";
     Class<?> clazz = Class.forName(className);
     Method method = clazz.getDeclaredMethod(methodName);
     Object instance = clazz.newInstance();
     method.invoke(instance);
}

详细说明已完成的工作:

  • 首先按名称加载类
  • 然后通过名称获取方法
  • 创建该类的新实例
  • 调用该实例的方法

【讨论】:

    猜你喜欢
    • 2019-04-11
    • 2018-07-07
    • 1970-01-01
    • 2020-08-16
    • 2019-02-27
    • 2020-07-20
    • 2020-04-12
    • 2015-07-12
    • 1970-01-01
    相关资源
    最近更新 更多