1

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:

for (Outer.Inner item : outer.getItems()) {
    item.getInnerX();
}

A NullPointerException is thrown inside getInnerX() because Outer.this is null.

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. 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.

The item attribute of Outer has annotations for the GSon converter:

@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)
Community
  • 1
  • 1
Pablo
  • 2,581
  • 3
  • 16
  • 31

1 Answers1

5

Retrofit uses Gson and Gson cheats. (As of this writing) It uses the sun.misc.Unsafe class to instantiate your class with 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 skips the constructor altogether, leaving that implicit Outer.this reference as 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:

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Thank you very much. I use inner classes to match the json structure data coming from the server. I will change my design like you said. – Pablo Apr 28 '16 at 01:04