-1

I am trying to do some work with LocationManager class and saw that I cannot instantiate it.

It is not an abstract class and I was under the impression that only classes marked as abstract could not be instantiated.

5
  • May be it constructor is private, if it's private you can not initialize outside of class Commented Apr 24, 2014 at 19:59
  • The constructor is private. You have to get the system's LocationManager service from Context#getSystemService(Context.LOCATION_SERVICE);
    – DeeV
    Commented Apr 24, 2014 at 20:00
  • 1
    You can't instantiate it directly, but something else you're using can and does (second paragraph of the docs). This is simple access control and is very common. Commented Apr 24, 2014 at 20:01
  • Well, that's something I missed and never realized. Thanks guys. Commented Apr 24, 2014 at 20:03
  • Keep up with the down votes guys, everyone here should be John Carmack. Commented Apr 24, 2014 at 20:11

1 Answer 1

2

For a more complete answer:

If you look at the source code for LocationManager, specifically line 303, you'll see it actually does have a public constructor ... but there's a special annotation:

/**
 * @hide - hide this constructor because it has a parameter
 * of type ILocationManager, which is a system private class. The
 * right way to create an instance of this class is using the
 * factory Context.getSystemService.
 */
public LocationManager(Context context, ILocationManager service) {
    mService = service;
    mContext = context;
}

The @hide annotation keeps the constructor out of the Javadoc and the IDE won't show it. You can read more about the @hide annotation in this SO Q and A

Basically, the class is designed so that you get it from the Context rather than instantiating it yourself. This is a fairly common design for things that require complex (or platform specific) configuration that you want to avoid having the user deal with.

Note that the @hide annotation and its handling are specific to Android.

This is similar to how the Builder or Factory pattern works, where only a builder/factory class can instantiate the object, although usually that's done with a private or package-private constructor in Java:

public class MyWidget
{
    private final Foo someObject; 
    // ... more stuff


    private MyWidget(Builder builder)
    {
        this.someObject = builder.someObject;
        // ... more stuff
    }

    public static class Builder
    {
        Foo someObject;

        public Builder() {}

        public Builder withFoo(Foo someObject)
        {
            this.someObject = someObject;
            return this;
        }

        public MyWidget build()
        {
            return new MyWidget(this);
        }
    }
}

Which gets invoked as:

MyWidget widget = new MyWidget.Builder().withFoo(someFoo).build();
3
  • 1
    Thank's a lot. I jut learned a lot from that post. Much appreciated. Commented Apr 24, 2014 at 20:25
  • 1
    @SpaceGhost True story; so did I. I've only played with Android a little and was expecting the standard idiom where the constructor was private or package-private - that's the answer I was expecting to type until I looked at the source. This is actually an interesting thing I didn't know about Android :) Commented Apr 24, 2014 at 20:39
  • 1
    Yeah, haha. I felt dumb asking but recalling what I knew about java, this stumped me a bit. I used google but didn't have much time to spare so every link I clicked didn't lead to an answer. Note to self: Look at source next time. Commented Apr 24, 2014 at 20:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.