Pra*_*ate 8 java access-specifier
我有以下课程
Hello.java
package speak.hello;
import java.util.Map;
import speak.hi.CustomMap;
import speak.hi.Hi;
public class Hello {
private Hi hi;
Hello(Hi hi) {
this.hi = hi;
}
public String sayHello() {
return "Hello";
}
public String sayHi() {
return hi.sayHi();
}
public Map<String, Object> getMap() {
return hi.getMap();
}
public void clearMap() {
hi.getMap().clear();
}
public void discardMap() {
CustomMap map = (CustomMap) hi.getMap();
map.discard();
}
public static void main(String[] args) {
Hello hello = new Hello(new Hi());
System.out.println(hello.sayHello());
System.out.println(hello.sayHi());
System.out.println(hello.getMap());
hello.clearMap();
System.out.println("--");
hello.discardMap();
}
}
Run Code Online (Sandbox Code Playgroud)
Hi.java
package speak.hi;
import java.util.HashMap;
import java.util.Map;
public class Hi {
public String sayHi() {
return "Hi";
}
public Map<String, Object> getMap() {
return new CustomMap<String, Object>();
}
}
Run Code Online (Sandbox Code Playgroud)
CustomMap.java
package speak.hi;
import java.util.HashMap;
public class CustomMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = -7979398843650044928L;
public void discard() {
System.out.println("Discarding Map");
this.clearCache();
this.clear();
}
@Override
public void clear() {
System.out.println("Clearing Map");
super.clear();
}
private void clearCache() {
System.out.println("Clearing Map");
}
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,直到我public从中删除访问说明符CustomMap
package speak.hi;
import java.util.HashMap;
class CustomMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = -7979398843650044928L;
public void discard() {
System.out.println("Discarding Map");
this.clearCache();
this.clear();
}
@Override
public void clear() {
System.out.println("Clearing Map");
super.clear();
}
private void clearCache() {
System.out.println("Clearing Map");
}
}
Run Code Online (Sandbox Code Playgroud)
编译器大喊大叫
类型speak.hi.CustomMap不可见
现在,如果我没有选项来修改speak.hi.CustomMap(第三方JAR等)有什么办法我仍然可以使用CustomMap从speak.hello.Hello?
我知道的一个选项是移动speak.hello.Hello到speak.hi.HelloNow Hello在包中speak.hi它可以访问包私有类Hi
有没有其他方法可以做到这一点?或许使用反思?
编辑:根据@StephenC的要求更新了其他详细信息
Ste*_*n C 10
有没有其他方法可以做到这一点?或许使用反思?
是.如果您的应用程序具有完全权限,则可以使用反射来绕过Java访问规则.
例如,private要从不同的类访问对象的字段,您需要:
Class对象.Class.getDeclaredField(...)方法获取Field字段的对象.Field.setAccessible(true)关闭访问检查.Class.getField(object, Field)以获取字段的值(如果是基本类型,则为盒装值).如果类本身不可访问,则需要确保不要在源代码中引用类标识符...'cos将导致编译错误.相反,将其引用分配给(例如)类型Object或其他可见超类型的变量,并反射性地对该实例执行更具体的操作.
正如您可能想象的那样,这很乏味且容易出错.建议你找一个更好的方法,比如:
(一般来说,如果你必须打破一个抽象,那么抽象本身或你使用它的方式都有问题.)
最后,我应该补充一点,不应信任的代码(应该)在安全沙箱中运行,该沙箱阻止了密钥反射操作的使用.
以下default方法使用反射调用范围类方法
public void discardMap() {
//CustomMap map = (CustomMap) hi.getMap();
//map.discard();
try {
Object o =hi.getClass().getMethod("getMap").invoke(hi);
Method m = o.getClass().getMethod("discard");
m.setAccessible(true);
m.invoke(o);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29387 次 |
| 最近记录: |