Java报错”IllegalAccessException”的原因以及解决办法

  • Post category:Java

ILLEGALACCESS异常是一个运行时异常,通常抛出此异常主要原因是因为Java程序试图访问一个受限制的类、方法或者构造器,并且这些受限制的方法、构造器或者类在继承层级中被标记为private或protected。这时我们需要采用反射或者暴力反射的方式来突破访问限制。

以下是几种常见的场景以及对应的解决方案:

场景一:访问私有对象或者成员变量

假设我们创建了一个Person类,该类中定义了firstName和lastName两个私有成员变量,同时我们定义了一个printFullName()方法,该方法访问了firstName和lastName两个私有成员变量,代码如下:

public class Person {
    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    private void printFullName() {
        System.out.println(firstName + " " + lastName);
    }
}

如果我们在main方法中想要创建一个Person对象并且调用printFullName()方法,如下:

public static void main(String[] args) {
    Person person = new Person("John", "Doe");
    person.printFullName();
}

则该代码会报出对私有方法的访问不合法的IllegalAccessException异常。此时我们可以使用Java的反射机制来解决:

public static void main(String[] args) throws Exception {
    Person person = new Person("John", "Doe");
    Method printFullNameMethod = person.getClass().getDeclaredMethod("printFullName");
    printFullNameMethod.setAccessible(true);
    printFullNameMethod.invoke(person);
}

这里我们使用了反射的方式获取私有方法printFullName(),然后通过setAccessible(true)方法来打开私有方法的访问权限,并使用invoke()方法来调用该方法。

场景二:访问受保护的构造器

同样的,如果我们创建了一个Person类,并且将其构造器标记为protected或private,则我们在外部访问时同样会抛出IllegalAccessException异常。以下是一个示例:

public class Person {
    protected Person() {
        System.out.println("Person constructor");
    }
}

public class Student extends Person {
    public static void main(String[] args) {
        new Person(); // illegal
        new Student(); // legal
    }
}

在上面的代码中,我们使用new Person()来访问Person类的受保护构造器,此时会抛出IllegalAccessException异常。但是我们使用new Student()来创建Student的实例是成功的,因为Person的构造器被该子类覆盖(open to subclass)而不是被隐藏(hidden)。

如果要访问受保护的构造器,则需要通过反射获取一个构造器对象,并调用该构造器的newInstance()方法来创建对象,如下所示:

public static void main(String[] args) throws Exception {
    Constructor<Person> constructor = Person.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    Person person = constructor.newInstance();
}

这里我们使用反射机制访问Person类的受保护构造器,并将构造器的可访问属性设置为true以便我们调用。最后使用constructor.newInstance()方法来创建Person对象。

以上是两种常见情况下Java报”IllegalAccessException”异常的原因以及使用反射机制解决问题的方法示例。