Java反射,Java.lang.IllegalAccessException错误
我的目标是: 第三个类将从控制台以字符串形式读取类的名称。在读取类的名称后,它将自动并动态(!)生成该类并调用其writeout方法。如果未从输入读取该类,则不会初始化该类 我正在接受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.
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,我将支持您。。也非常感谢你对我的理解。。