2010-04-04 3 views
1

Моя цель:Java Reflection, java.lang.IllegalAccessException Ошибка

Третий класс прочитает имя класса как String, из console.Upon чтения имя класса, он будет автоматически и динамически (!) сгенерируйте этот класс и вызовите его метод записи. Если этот класс не считывается с ввода, он не будет инициализирован.

И принимаю java.lang.IllegalAccessException: Class deneme.class3 can not access a member of class java.lang.Object with modifiers "protected" Ошибка. И ı не знаю, как это можно исправить. Может ли кто-нибудь мне помочь?

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();    
    } 
} 
+0

Backticks работают только с встроенным кодом. Для блоков кода, отступ с четырьмя пробелами (точнее, нажмите кнопку и пусть редактор сделает это за вас). – Thomas

+0

Если вы хотите следовать соглашению об именах (и нет причин, по которым вы не должны), вы должны использовать верблюжий корпус для имен типов, например. 'Object',' String', 'BufferedInputStream'. – polygenelubricants

ответ

2

какую функцию вы пытаетесь выполнить точно? выглядит так, будто вы просто выбираете первый метод, не проверяя, что это такое. попытайтесь выбрать конкретный метод, который является общедоступным.

0

Похоже, он попытается вызвать первый метод Object. Кажется, подобрал clone. Для этого потребуется setAccessible(true). Вероятно, есть и другие проблемы с вашим кодом.

0

Вышеприведенное кажется мне очень смущенным. Ни в коем порядке:

  1. вы не используете имя класса введенного стандартного ввода
  2. вы загружаете класс через forName(), но это не одна вы указываете в 1. выше
  3. вы должны найти метод writeout() этого класса, используя getDeclaredMethods() или аналогичный.

Короче говоря, я думаю, что у вас есть все необходимые методы/API, необходимые для загрузки класса, который кто-то указывает в командной строке, экземпляр экземпляра, а затем вызов метода. Это просто, что на данный момент ваш класс загрузки/расположения методов не делает выше.

1

Непонятно, что вы делаете в своем коде.

Похоже, первым вы объявляете 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(); 

(конечно YourClass должен будет реализовать интерфейс Invokable)

Этот подход четко определяет, что программа сможет динамически создавать, и то, что вы должны разрешить делать с этими объектами, не беспокоясь о поиске методов или позволяющих странным вещам бывает ..

+0

+1 для предложения интерфейса. – polygenelubricants

1

Это самая вопиющая проблема с кодом:

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

Вы просто захватывая первый объявленный метод c2, который Object.class. Кто знает, что такое метод? (в моем случае это protected void java.lang.Object.finalize() throws 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? 

Предположительно вы можете сделать это вместо:

  1. Прочитайте имя класса, чтобы найти
  2. Найти этот класс используя Class.forName
  3. Отражение на этом классе до финиша d в 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); 

Это будет печатать "class3" и "class4" в зависимости от имени класса вы набираете Вы должны были бы сделать его более надежным, но это. иллюстрирует идею.


Следует отметить, что, если это возможно, вы должны сделать эти динамически созданный тип implements SomeInterface (см ответ Джека). Также читайте Эффективное Java 2nd Edition, п. 53: Предпочитают интерфейсы для отражения.

+0

, но когда я использую «Класс writeoutClass = Class.forName (строка)» вместо «Class c1 = Class.forName (« java.lang.String »)», я принимаю java.lang.ClassNotFoundException – rubby

+0

Ну, что вы вводите? Если вы введете имя мусора, то, конечно, этот класс не может быть найден !!! Вы должны ввести имя _fully qual_ класса, которое вы хотите найти. Являются ли 'class3' и' class4' в пакете? Возможно, называется «deneme»? – polygenelubricants

+0

Прощайте, пожалуйста ... Но ı не знаю, как ı может написать «полностью квалифицированное» название класса, которое ı хочет его найти. Конечно, класс3 и класс4 в моем пакете. – rubby