我在尝试使用以下方法重写方法时遇到了奇怪的行为默认访问器 (ex: void run()
)。
根据Java规范,如果类属于同一个包,则类可以使用或覆盖基类的默认成员。
当所有类从同一个类加载器加载时,一切正常。
但是如果我尝试从中加载子类separate类加载器则多态性不起作用。
这是示例:
应用程序.java:
import java.net.*;
import java.lang.reflect.Method;
public class App {
public static class Base {
void run() {
System.out.println("error");
}
}
public static class Inside extends Base {
@Override
void run() {
System.out.println("ok. inside");
}
}
public static void main(String[] args) throws Exception {
{
Base p = (Base) Class.forName(Inside.class.getName()).newInstance();
System.out.println(p.getClass());
p.run();
} {
// path to Outside.class
URL[] url = { new URL("file:/home/mart/workspace6/test2/bin/") };
URLClassLoader ucl = URLClassLoader.newInstance(url);
final Base p = (Base) ucl.loadClass("Outside").newInstance();
System.out.println(p.getClass());
p.run();
// try reflection
Method m = p.getClass().getDeclaredMethod("run");
m.setAccessible(true);
m.invoke(p);
}
}
}
Outside.java:应该位于单独的文件夹中。否则类加载器将是相同的
public class Outside extends App.Base {
@Override
void run() {
System.out.println("ok. outside");
}
}
输出:
class App$Inside
ok. inside
class Outside
error
ok. outside
然后我打电话Outside#run()
I got Base#run()
(输出中的“错误”)。反射工作正常。
怎么了?或者这是预期的行为?
我可以以某种方式解决这个问题吗?
From Java虚拟机规范:
5.3 创建与加载
...
在运行时,类或接口是
不仅由其名称决定,而且
通过一对:其完全限定名称
及其定义类加载器。每个
这样的类或接口属于
单身的运行时包。运行时
类或接口的包是
由包名和
定义类的类加载器或
界面。
5.4.4 Access Control
...
A field or method R is accessible to a class
or interface D if and only if any of
the following conditions is true:
- ...
- R 是
protected
或包私有(即,既不是public
nor
protected
nor private
), 并且是
由同一类中声明
运行时包为 D.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)