org.deeplearning4j.nn.layers.BaseOutputLayer ll = (org.deeplearning4j.nn.layers.BaseOutputLayer) model.getLayer(0);
Field f = Class.forName("org.deeplearning4j.nn.layers.BaseOutputLayer").getDeclaredField("solver");
f.setAccessible(true);
Solver s = (Solver) f.get(ll);
"Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform"
这是以下代码snapts来演示 Reflection 的基本概念
Reflection1.java
public class Reflection1{
private int i = 10;
public void methoda()
{
System.out.println("method1");
}
public void methodb()
{
System.out.println("method2");
}
public void methodc()
{
System.out.println("method3");
}
}
Reflection2.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection2{
public static void main(String ar[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
Method[] mthd = Reflection1.class.getMethods(); // for axis the methods
Field[] fld = Reflection1.class.getDeclaredFields(); // for axis the fields
// Loop for get all the methods in class
for(Method mthd1:mthd)
{
System.out.println("method :"+mthd1.getName());
System.out.println("parametes :"+mthd1.getReturnType());
}
// Loop for get all the Field in class
for(Field fld1:fld)
{
fld1.setAccessible(true);
System.out.println("field :"+fld1.getName());
System.out.println("type :"+fld1.getType());
System.out.println("value :"+fld1.getInt(new Reflaction1()));
}
}
}
如果使用Spring,ReflectionTestUtils提供了一些方便的工具,只需要很少的努力就可以提供帮助 . 它被描述为"for use in unit and integration testing scenarios" . 还有一个名为ReflectionUtils的类似的类,但这被描述为"Only intended for internal use" - 请参阅this answer以解释这意味着什么 .
11 回答
您可以使用Manifold's @JailBreak 进行直接的,类型安全的Java反射:
@JailBreak
解锁编译器中的foo
局部变量,以便直接访问Foo
层次结构中的所有成员 .同样,您可以使用 jailbreak() 扩展方法进行一次性使用:
通过
jailbreak()
方法,您可以访问Foo
层次结构中的任何成员 .在这两种情况下,编译器都会为您安全地键入字段访问,就像公共字段一样,而Manifold会为您生成有效的反射代码 .
了解有关Manifold的更多信息 .
使用Soot Java Optimization框架直接修改字节码 . http://www.sable.mcgill.ca/soot/
Soot完全用Java编写,适用于新的Java版本 .
关于反射的另一个注意事项:我在一些特殊情况下观察到,当不同包中存在多个具有相同名称的类时,顶部答案中使用的反射可能无法从对象中选择正确的类 . 因此,如果您知道对象的package.class是什么,那么最好访问其私有字段值,如下所示:
(这是不适合我的示例类)
反射不是解决问题的唯一方法(即访问类/组件的私有功能/行为)
另一种解决方案是从.jar中提取类,使用(例如)Jode或Jad对其进行反编译,更改字段(或添加访问器),并针对原始.jar重新编译它 . 然后将新的.class放在类路径中的
.jar
之前,或者将其重新插入.jar
中 . (jar实用程序允许您提取并重新插入现有的.jar)如下所述,这解决了访问/更改私有状态的更广泛问题,而不是简单地访问/更改字段 .
当然,这需要
.jar
不要签名 .从apache commons-lang3尝试FieldUtils:
您需要执行以下操作:
要访问私有字段,您需要从类的声明字段中获取它们,然后使它们可访问:
EDIT :正如aperkins所评论的那样,两者都访问该字段,将其设置为可访问并检索该值将全部抛出
Exception
,尽管您需要注意的唯一已检查的异常在上面进行了评论 .如果您通过与声明字段不对应的名称请求字段,则会抛出
NoSuchFieldException
.如果该字段不可访问,则会抛出
IllegalAccessException
(例如,如果该字段是私有的,并且由于错过了f.setAccessible(true)
行而无法访问该字段 .可能抛出的
RuntimeException
是SecurityException
s(如果JVM的SecurityManager
将不允许您更改字段的可访问性),或者IllegalArgumentException
s,如果您尝试访问非字段's class'类型的对象上的字段:另一个尚未提及的选项:使用 Groovy . Groovy允许您访问私有实例变量,作为语言设计的副作用 . 无论你是否有野外吸气器,你都可以使用
使用 Reflection in Java ,您可以访问一个类的所有
private/public
字段和方法到另一个类 . 但是根据 drawbacks 中的 Oracle documentation,他们建议:"Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform"
这是以下代码snapts来演示 Reflection 的基本概念
Reflection1.java
Reflection2.java
希望它会有所帮助 .
正如oxbow_lakes所提到的,你可以使用反射来绕过访问限制(假设你的SecurityManager会让你) .
也就是说,如果这个类的设计非常糟糕以至于让你诉诸于这样的hackery,那么也许你应该寻找替代方案 . 当然,这个小小的黑客现在可能会为你节省几个小时,但是你需要花多少钱呢?
如果使用Spring,ReflectionTestUtils提供了一些方便的工具,只需要很少的努力就可以提供帮助 . 它被描述为"for use in unit and integration testing scenarios" . 还有一个名为ReflectionUtils的类似的类,但这被描述为"Only intended for internal use" - 请参阅this answer以解释这意味着什么 .
要解决发布的示例: