在 Java 应用程序中,我声明了两个类,一个类 (One) 在 ClassLoader A 中声明,另一个类 (Two) 在 ClassLoader B 中声明。ClassLoader A是B的 parent 。这两个类都具有相同的包(即:org.test)。
虽然 A 是 B 的父类加载器,但我似乎无法从 Two 事件访问 One 的包私有(private)方法或变量,我得到一个 IllegalAccessError异常。我了解包私有(private)可访问性基于包名称和类加载器。
有没有办法重新关联One和Two,以便Two可以访问One的封装私有(private)元素?
下面是证明这一点的测试:
package org.test;
public class ClassLoaderTest {
@Test
public void testLoading() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
One one = new One();
one.value = "test";
MemoryClassLoader classLoader = new MemoryClassLoader();
String name = one.getClass().getPackage().getName() + ".Two";
classLoader.add(name,
"package org.test;\n" +
"\n" +
"public class Two{\n" +
" public static String getValue(One one){\n" +
" return one.value;\n" +
" }\n" +
"}");
Class<?> twoClass = classLoader.loadClass(name);
assertEquals("test", twoClass.getMethod("getValue", One.class).invoke(null, one));
}
}
public class One{
String value;
}
可以找到MemoryClassLoader here .
哪些错误:
testLoading(org.test.ClassLoaderTest) Time elapsed: 0.214 sec <<< ERROR!
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.test.ClassLoaderTest.testLoading(ClassLoaderTest.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
....
Caused by: java.lang.IllegalAccessError: tried to access field org.test.One.value from class org.test.Two
at org.test.Two.getValue(Two.java:5)
... 34 more
谢谢。
编辑:
我已经制作了一个 Gist,其中包含一个自包含测试来演示这个 here .
最佳答案
Is there a way to re-associate One and Two so that Two can access One's Package Private elements?
简单回答: 反射(reflection):是;没有反射:否。
详细答案:Java 有自己的机制来控制访问,防止包或类的用户依赖于该包或类的实现的不必要细节。如果允许访问,则称被访问的实体是可访问的。 Accessibility 是一个静态属性,可以在编译时确定;它仅取决于类型和声明修饰符。
If the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class that encloses the declaration of the member or constructor. A private class member or constructor is accessible only within the body of the top level class that encloses the declaration of the member or constructor. It is not inherited by subclasses.
因此,在 Java SE 中不使用反射 API 是不可能的。
如果使用 Reflection API,那么可访问性的静态内省(introspection)将更改为动态。类是动态加载的,绑定(bind)是动态完成的,对象实例是在需要时动态创建的。历史上不太活跃的是操纵“匿名”类的能力。在此上下文中,匿名类是在运行时加载或呈现给 Java 类的类,并且其类型以前不为 Java 程序所知。
使用反射 API 的类和方法访问代码片段
Object o = hi.getClass().getMethod("foo").invoke(hi);
Method m = o.getClass().getMethod("bar");
m.setAccessible(true);
m.invoke(o);
深入了解 Java Reflection API .
并不总是需要证明不可能本身就表示我可能。在这种情况下,Reflection API 已经为我们重新发明了轮子,我们不应该寻求从头开始重新发明它。(轻描淡写,无意冒犯。)
希希尔
关于java - 访问父/子类加载器之间的包私有(private)元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21960255/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee