Как загрузить финальный класс, используя отражение Java - PullRequest
2 голосов
/ 19 августа 2011

Я пытаюсь загрузить окончательный класс, используя следующий код

final ClassLoader myClassLoader = ClassLoader.getSystemClassLoader();
final String classNameToBeLoaded = "demo";
final Class myClass = myClassLoader.loadClass(classNameToBeLoaded);
    // create a new instance
final Constructor cons = demo.class.getConstructor();......(1)
final Object whatInstance = cons.newInstance();

, мне не возвращаются такие исключения метода ... на 1. В чем проблема ...?

Ответы [ 4 ]

2 голосов
/ 19 августа 2011

Не видя фактического определения рассматриваемого класса, мы можем только догадываться, что у класса может не быть открытого конструктора по умолчанию (без параметров).

На самом деле проблема в том, что вы пытаетесь получить конструктор класса Class вместо реального класса:

final Class myClass = myClassLoader.loadClass(classNameToBeLoaded);
    // create a new instance
final Constructor cons = demo.class.getConstructor();......(1)

Вместо этого вызов метода в последней строке должен быть myClass.getConstructor(): myClass относится к объекту типа Class, который является токеном класса для вашего demo класса. Таким образом, myClass.class относится к токену класса myClass, который сам является классом Class. Который действительно не имеет открытых конструкторов, так как он не предназначен для реализации именно так.

Кстати, класс или переменная final не имеют ничего общего с отражением или проблемами загрузки классов. Вы всегда можете загрузить класс при условии, что он найден в classpath, является открытым и имеет открытый конструктор (хотя, если конструктор имеет параметры, он немного сложнее, чем ваш код выше).

1 голос
/ 19 августа 2011
final Constructor cons = demo.class.getConstructor();

Если это не удается, это означает одно из двух:

либо нет конструктора по умолчанию, либо он не является общедоступным (class.getConstructor(...) возвращает только общедоступные конструкторы, и если бы был общедоступный конструктор по умолчанию, вы бы не делали этого в первую очередь).

Вы можете решить вторую проблему, используя getDeclaredConstructor(...) вместо getConstructor(), он находит конструкторы со всеми видимостьми:

final Constructor<Demo> cons = demo.class.getDeclaredConstructor();
Demo demo = cons.newInstance();

Первая проблема сложнее, очевидно: -)

0 голосов
/ 19 августа 2011

Ваш код работает, если у демонстрационного класса есть конструктор по умолчанию или открытый конструктор без аргументов. Если у вас есть приватный конструктор и вы пытаетесь использовать его для создания экземпляра, вы получите

java.lang.IllegalAccessException: Class ... can not access a member of class demo with modifiers "private"

Вам просто нужно использовать правильный конструктор.

Предполагается, что у вашего класса есть открытый конструктор, который получает параметр int:

public final class Demo {
    private final int i;

    public Demo(int i) {
        this.i = i;
    }

    public void doSmth() {
        System.out.print("Your number is: " + i);
    }
}

Здесь Главный класс:

import java.lang.reflect.Constructor;

public class Main {
    public static void main(String[] args) throws Exception {
        final ClassLoader myClassLoader = ClassLoader.getSystemClassLoader();
        final String classNameToBeLoaded = "Demo";
        final Class myClass = myClassLoader.loadClass(classNameToBeLoaded);
        // create a new instance
        final Constructor cons = Demo.class.getConstructor(int.class);
        int i = 10;
        final Object whatInstance = cons.newInstance(i);
        // prints: Your number is: 10
        ((Demo) whatInstance).doSmth();
    }
}
0 голосов
/ 19 августа 2011
try {
    Object instance = Class.forName("com.foo.Demo").newInstance();
} catch(ClassNotFoundException e) {
    // do something
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...