[英]Inner class reference to enclosing class instance is null
I have a class that has an inner class and a collection of the inner instances: 我有一个具有内部类和内部实例集合的类:
public class Outer {
private List<Inner> items = new ArrayList<Inner>();
...
public List<Inner> getItems(){
return this.items;
}
public int getOuterX() {
...
}
...
public class Inner {
...
public int getInnerX(){
return Outer.this.getOuterX(); // this line throws the exception
}
}
}
In other class I iterate over the items of an instance of Outer
and call getInnerX()
to each one: 在其他类中,我遍历Outer
实例的项目,并对每个实例调用getInnerX()
:
for (Outer.Inner item : outer.getItems()) {
item.getInnerX();
}
A NullPointerException
is thrown inside getInnerX()
because Outer.this
is null
. 因为Outer.this
为null
所以在getInnerX()
内部抛出NullPointerException
。
I don't know how this can happen. 我不知道这怎么会发生。
EDIT: 编辑:
I was preparing the example like @Sotirios Delimanolis asked for and i could not reproduce the error. 我正在准备@Sotirios Delimanolis之类的示例,但我无法重现该错误。 So its something that i did not include in the question. 因此,这是我未在问题中包括的内容。
I am using retrofit2
and Outer
object is created based on a json
response from the server. 我正在使用retrofit2
并且基于服务器的json
响应创建了Outer
对象。
The item attribute of Outer
has annotations for the GSon
converter: Outer
的item属性具有GSon
转换器的注释:
@SerializedName("items")
@Expose
private List<Inner> items = new ArrayList<Inner>();
Outer has no constructor defined neither does Inner. 外部没有定义构造函数,内部也没有定义。
Here is the stack trace: 这是堆栈跟踪:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String
com.example.server_comunication.datatypes.OrderResponse$Order.getStatus()' on a null object reference
at com.example.server_comunication.datatypes.OrderResponse$Order$Supply.forPlacement(OrderResponse.java:408)
at com.example.server_comunication.datatypes.OrderResponse$Order$Supply.getRemaining(OrderResponse.java:423)
at com.example.uiHelpers.UIFactoryPanels.drawPanelSuppliesEditor(UIFactoryPanels.java:142)
at com.example.OrderFragment.onCreateView(OrderFragment.java:85)
at android.app.Fragment.performCreateView(Fragment.java:2053)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.app.BackStackRecord.run(BackStackRecord.java:833)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:483)
at android.support.v13.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:145)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1177)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1025)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1545)
at android.view.View.measure(View.java:17430)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:668)
at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:735)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17430)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560)
at android.view.View.measure(View.java:17430)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2001)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1166)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1372)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
Retrofit uses Gson and Gson cheats. 改造使用Gson和Gson作弊。 (As of this writing) It uses the sun.misc.Unsafe
class to instantiate your class with allocateInstance
. (截至撰写本文时)它使用sun.misc.Unsafe
类使用allocateInstance
实例化您的类。 This skips any constructors altogether. 这将完全跳过所有构造函数。
In the case of an inner class, any declared constructor will implicitly declare its first parameter as the enclosing type to represent the enclosing class' instance . 对于内部类, 任何已声明的构造函数都将隐式声明其第一个参数为包含类型,以表示包含类的实例 。 There's no way for Gson to create an instance of that enclosing class, but even if it did, that doesn't matter. Gson无法创建该封闭类的实例,但是即使这样做,也没关系。 Gson skips the constructor altogether, leaving that implicit Outer.this
reference as null
. Gson完全跳过了构造函数,将隐式Outer.this
引用保留为null
。
The easiest solution is to change your design, get rid of the inner class(es). 最简单的解决方案是更改您的设计,摆脱内部类。 Alternatively, you can register and use a custom deserializer. 或者,您可以注册并使用自定义解串器。 There are examples in the posts below. 以下帖子中有示例。
Related posts: 相关文章:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.