简体   繁体   English

对封闭类实例的内部类引用为null

[英]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.thisnull所以在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM