Java反射,Java.lang.IllegalAccessException错误

Java反射,Java.lang.IllegalAccessException错误,java,reflection,Java,Reflection,我的目标是: 第三个类将从控制台以字符串形式读取类的名称。在读取类的名称后,它将自动并动态(!)生成该类并调用其writeout方法。如果未从输入读取该类,则不会初始化该类 我正在接受java.lang.IllegalAccessException:类deneme.class3无法访问带有修饰符“protected”的类java.lang.Object的成员错误。而且我不知道我怎么能修好它。。 有人能帮我吗 import java.io.*; import java.lang.reflect.

我的目标是:

第三个类将从控制台以字符串形式读取类的名称。在读取类的名称后,它将自动并动态(!)生成该类并调用其writeout方法。如果未从输入读取该类,则不会初始化该类

我正在接受
java.lang.IllegalAccessException:类deneme.class3无法访问带有修饰符“protected”的类java.lang.Object的成员
错误。而且我不知道我怎么能修好它。。
有人能帮我吗

import java.io.*;

import java.lang.reflect.*;


 class class3
{

    public void run()
      {
        try
        {    
            BufferedReader reader= new BufferedReader(new InputStreamReader(System.in)); 

              String line=reader.readLine();

              Class c1 = Class.forName("java.lang.String");
              Object obj = new Object();
              Class c2 = obj.getClass();

              Method writeout = null; 
              for( Method mth : c2.getDeclaredMethods() ) {                  
                     writeout = mth; 
                     break;                  
              } 
              Object o = c2.newInstance(); 
              writeout.invoke( o );              

        }
        catch(Exception ee)
        {
       System.out.println("ERROR! "+ee);
        }

        }

  public void writeout3()
  {
      System.out.println("class3");
  }
      }

class class4
{
  public void writeout4()
  {
    System.out.println("class4");
  }
}

class ornek {


    public static void main(String[] args) {
       System.out.println("Please Enter Name of Class : ");
       class3 example = new class3();
       example.run();               
    }
}

你到底想执行什么函数? 在我看来,您只是选择了第一种方法,而没有实际检查它是什么。
尝试选择一个特定的公共方法。

看起来它将尝试调用
对象的第一个方法。似乎已选择克隆
clone
。这将需要
setAccessible(true)
。您的代码可能还有其他问题。

我对上述内容感到非常困惑。没有顺序:

  • 您没有使用在标准输入中输入的类的名称
  • 您正在通过
    forName()
    加载一个类,但它不是您在1中指定的类。在上面
  • 您应该使用
    getDeclaredMethods()
    或类似方法找到该类的
    writeout()
    方法

  • 简而言之,我认为您已经具备了加载某人在命令行上指定的类、实例化实例、然后调用方法所需的所有方法/API。只是目前您的类加载/方法位置没有执行上述操作。

    不清楚您在代码中执行的操作

    看起来,首先声明
    c1
    ,即
    java.lang.String
    ,而不使用它。。然后加载一个新的
    java.lang.Object
    ,检查它声明的方法,然后选择第一个作为
    writeout
    找到的方法,然后在不知道调用什么的情况下尝试调用它

    要做您试图解释的事情,我建议您:

    例如,使用要动态调用的方法定义一个像
    Invokable
    这样的接口

    interface Invokable {
      public void invokeMe();
    }
    
    然后,无论何时通过加载名称生成新类,都可以将其强制转换到接口并调用该方法,而不会发疯:

    Class<?> class = Class.forName("your.YourClass");
    Object target = class.newInstance();
    
    if (target instanceof Invokable)
     ((Invokable)target).invokeMe();
    
    Class Class=Class.forName(“your.YourClass”);
    Object target=class.newInstance();
    if(可调用的目标实例)
    ((可调用)target.invokeMe();
    
    (当然,
    YourClass
    必须实现
    可调用的接口)


    这种方法清楚地定义了程序将能够动态实例化的内容,以及允许您对这些对象执行的操作,而不必担心搜索方法或允许发生奇怪的事情。

    这是代码中最明显的问题:

    Method writeout = null; 
    for( Method mth : c2.getDeclaredMethods() ) {                  
       writeout = mth; 
       break;                  
    } 
    
    您只需要获取
    c2
    的第一个声明方法,即
    Object.class
    。谁知道方法是什么?(在我的例子中,
    受保护的void java.lang.Object.finalize()抛出java.lang.Throwable

    另一个问题是:

    String line=reader.readLine();
    // presumably you're reading the name of the class to find here...
    
    Class c1 = Class.forName("java.lang.String");
    // why do you need String.class? what is c1 used for?
    
    Object obj = new Object();
    Class c2 = obj.getClass();
    // so now c2 is Object.class? what are you trying to accomplish?
    
    您可能希望这样做:

  • 读取要查找的类的名称
  • 使用
    class.forName
  • 反思该类以找到
    writeout*
    方法
  • 意思是这样的:

    String line = reader.readLine();
    
    Class<?> writeoutClass = Class.forName(line);
    
    Method writeout = null;
    for (Method mth : writeoutClass.getDeclaredMethods()) {
        if (mth.getName().startsWith("writeout")) {
            writeout = mth;
            break;
        }
    }
    
    Object o = writeoutClass.newInstance();
    writeout.invoke(o);
    
    String line=reader.readLine();
    Class writeoutClass=Class.forName(行);
    方法writeout=null;
    对于(方法mth:writeoutClass.getDeclaredMethods()){
    if(mth.getName().startsWith(“writeout”)){
    注销=mth;
    打破
    }
    }
    对象o=writeoutClass.newInstance();
    注销。调用(o);
    
    这将根据您键入的类名打印
    “class3”
    “class4”
    。你需要使它更健壮,但它说明了这个想法



    应该提到的是,如果可能,您应该使这些动态创建的类型
    实现SomeInterface
    (参见Jack的答案)。另外,请阅读《有效Java第二版》第53项:更喜欢接口而不是反射。

    反勾号仅适用于内联代码。对于代码块,请使用四个空格缩进(或者更确切地说,单击按钮,让编辑器为您进行缩进)。如果您想遵循命名约定(并且没有理由不这样做),您应该使用驼峰式大小写作为类型名称,例如
    对象
    字符串
    BufferedInputStream
    。但是当我使用“Class writeoutClass=Class.forName(行)”而不是“Class c1=Class.forName”(“java.lang.String”)“,我正在学习java.lang.ClassNotFoundException。那么,您输入了什么?如果您键入垃圾名称,那么当然找不到该类!!!您必须键入要查找的类的完全限定名。
    class3
    class4
    是否在一个包中?也许是打电话给deneme?请放松。。。但ı不知道ı如何写出ı想要找到的类的“完全限定”名称。当然,我的包中有class3和class4。如果您不知道要查找的类的名称,则无法按名称查找它(即
    class.forName
    的用途)。您的问题中的代码中没有
    package
    声明,但错误消息提到“
    classdeneme.class3
    ”,因此我假设代码实际上在
    package deneme中。在这种情况下,试着键入
    deneme.class3
    deneme.class4
    。是的,你知道你想做什么:1.阅读类的名称以查找2.使用class.forName 3查找该类。反思该类以查找writeout*方法,就是这样的方法。。现在我将尝试deneme.class3和deneme.class4,我将支持您。。也非常感谢你对我的理解。。