2016-04-01 4 views
1

Я пытаюсь сделать код для динамической загрузки класса и использовать его для создания новых экземпляров и запускает броски. Я могу создать экземпляр из недавно загруженного класса, используя этот метод: myClass.newInstance();. Но я не могу использовать его как тип. Например: myClass myObj = new myClass(); Это не работает. Можно ли как-то это сделать?Можно ли динамически загружать класс и использовать его как тип?

Это код, который я пытался сделать:

URL classUrl; 
classUrl = new URL("file:///C:/classes/"); 
URL[] classUrls = { classUrl }; 
URLClassLoader ucl = new URLClassLoader(classUrls); 
Class c = ucl.loadClass("Operation"); 
Class MyIn = ucl.loadClass("MyInter"); 
Object o = c.newInstance(); //IT WORKS 
System.out.println(((MyIn) o).sum(2, 4)); //IT DOES NOT WORK. Message: MyIn cannot be resolved to a type 
+0

Вы спрашиваете, почему вы не можете использовать класс во время компиляции, когда вы загрузили его после компиляции? –

+0

Вы правы, но я хотел бы сделать это динамически, загружая MyIn динамически, вместо этого помещая его в проект. –

+0

'MyIn' в вашем коде - это имя переменной, и вы позже попытаетесь применить' o' к типу интерфейса ' MyIn' - обратите внимание на те же персонажи! Измените имя переменной 'MyIn' на нечто более типичное для Java, например' myIn'. Вы также можете попытаться отличить o от экземпляра 'MyIn', используя:' MyIn instance = MyIn.getClass(). Cast (o); ', а затем использовать его в своем приложении, как и любой другой, динамически загруженный экземпляр' MyIn' –

ответ

5

Поскольку вы не знаете Мьин во время компиляции, необходимо использовать отражение не только для создания экземпляра класса, как и вы, но и для вызова методов.

Что-то вдоль линий:

MyIn.getDeclaredMethod("sum",Integer.TYPE,Integer.TYPE).invoke(o,2,4); 

Смотрите, например https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html

+1

Вы можете вызвать его методы напрямую, если они находятся в интерфейсе, который известен во время компиляции и реализуется динамически загруженным классом. –

+0

MyIn - это inteface, который я пытаюсь загрузить. Вот почему я пытаюсь сделать бросок на o. У интернитуры есть декларация метода sum.Запустив строку, которую вы мне дали, она отображает новую ошибку: Caught exception: java.lang.NoSuchMethodException: MyEx.sum() –

+0

См. API для getDeclaredMethod, нужны типы параметров. –

1

Вы не можете напрямую использовать класс во время компиляции, что при загрузке позже во время выполнения.

Однако, вы можете работать непосредственно через один или несколько интерфейсов реализованных загруженных классов. Как правило, сами интерфейсы включаются в путь класса компиляции как кода загрузки, так и загруженного кода.

Общие интерфейсы определяют ожидаемое взаимодействие во время компиляции. Загруженный код определяет поведение во время выполнения.

Например, вы можете загрузить этот динамически загруженный класс:

public class Operation implements MyInterface { ... } 

А затем взаимодействовать с ним через общий интерфейс:

Class c = ucl.loadClass("mypackage.Operation"); 
Object o = c.newInstance(); //IT WORKS 
MyInterface operation = (MyInterface) o; 

Теперь вы можете взаимодействовать непосредственно с методами через общий интерфейс.

System.out.println(operation.sum(2, 4)); 

Конструкторы

For example: myClass myObj = new myClass(); It doesn't work. Is it possible to perform somehow?

Вы можете создать завод с имени конструкторами в динамически загружаемой кода. На заводе также будет реализован общий интерфейс.

Class cFactory = ucl.loadClass("mypackage.MyFactory"); 
MyFactoryInterface factory = (MyFactoryInterface) cFactory.newInstance();  
MyInterface myObj = factory.makeOperation(); 
+0

Энди, спасибо за ответ. Как я могу использовать этот интерфейс, не помещая его в свой проект? Поскольку, технически, мой код не знает, что мой недавно загруженный класс реализовал интерфейс под названием «MyInterface», правильно? Мой код не сможет увидеть это inteface, когда я объявляю его там. Этот загруженный класс также был динамически скомпилирован. И то, что было создано, было только файлом .class. Я динамически компилировал «Operation.java», и теперь у меня есть в моей папке «Operation.java» и «Operation.class». Я беру Operation.class и загружаю его. Но как я могу использовать интерфейс «MyInter», который выполняет Операция? –

+1

@ AraújoFilho Как вы заявили интерфейс, как вы написали «Операция», интерфейс должен быть где-то доступным, иначе «Операция» не должна компилироваться. Обычно (например, в подключаемых приложениях) есть интерфейс, уже присутствующий в главном коде, чтобы разрешить вызов динамически загружаемых классов, которые должны хотя бы реализовать методы, заданные интерфейсом, иначе может оказаться трудным выполнить динамически загруженные классы per se –

+0

Thx @RomanVottner. Я понял. Итак, нет ли способа динамически загружать интерфейс? –