Domanda

Re-edited...

I'd like to use a superclass constructor which is hidden by the "@hide" Android tag (or whatever it is).

I'm about to extend a class which has been already extended twice (within the Android OS). I'd like to create my own subclass (i.e. outside the Android OS). Example subclass, taken from Android sources:

public class WifiP2pDnsSdServiceInfo extends WifiP2pServiceInfo {
    ...
    private WifiP2pDnsSdServiceInfo(List<String> queryList) {
        super(queryList); // <-- this is what I'm trying to do, too
    }

    public static WifiP2pDnsSdServiceInfo newInstance(String instanceName,
            String serviceType, Map<String, String> txtMap) {
        ...
        ArrayList<String> queries = new ArrayList<String>();
        ...
        return new WifiP2pDnsSdServiceInfo(queries);
    }
}

The superclass looks like this:

public class WifiP2pServiceInfo implements Parcelable {
    ...
    // this is marked as @hidden therefore inaccessible!
    protected WifiP2pServiceInfo(List<String> queryList) {
        if (queryList == null) {
            throw new IllegalArgumentException("query list cannot be null");
        }
        mQueryList = queryList;
    }
}

And all I want to do is to make another kind of WifiP2pServiceInfo, similar to the WifiP2pDnsSdServiceInfo example above. I can't just inherit & call super() because the superclass constructor is tagged by Android's "@hide", therefore unusable without reflection for non-system programmers.

So my question is how to access / call the superclass constructor if I can't do it by a plain super() call? Reflection should come handy here but I'm not very experienced in Java programming.

È stato utile?

Soluzione

After some research I'm able to answer the question by myself.

Short answer: I can't do this because if the superclass constructor is protected and hidden, the compiler is going to complain even if I found a way how to call the constructor via reflection.

Long answer: it turns out it's not so complicated to "unhide" this stuff. Following this tutorial I'm able to extend the class to my needs.

See? A lot of noise for nothing, this is the answer I was looking for.

Altri suggerimenti

You want to find that constructor and set its availability to true.

But this is a dangerous operation that you should not attempt lightly. It's a dirty secret that private need not mean private, but I would still expect you to honor the wishes of the class designer and not circumvent.

Besides, you don't need to. If I understand your requirement, I've posted an example that will do what you want.

This works, because of this:

The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

I think you've confused the meaning of the protected modifier.

Parent w/ protected ctor:

package foo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Parent with protected constructor
 * User: MDUFFY
 * Date: 3/27/14
 * Time: 5:18 PM
 * @link http://stackoverflow.com/questions/22698501/reflection-how-to-call-superclass-constructor-which-is-hidden/22698543?noredirect=1#comment34586243_22698543
 */
public class Foo {
    private List<String> x;

    protected Foo(List<String> y) {
        this.x = ((y == null) ? new ArrayList<String>() : new ArrayList<String>(y));
    }

    public List<String> getX() {
        return Collections.unmodifiableList(this.x);
    }

    @Override
    public String toString() {
        return "Foo{" +
                "x=" + x +
                '}';
    }
}

Child extends Parent:

package bar;

import foo.Foo;

import java.util.Arrays;
import java.util.List;

/**
 * Child of parent with protected ctor
 * User: MDUFFY
 * Date: 3/27/14
 * Time: 5:22 PM
 * @link http://stackoverflow.com/questions/22698501/reflection-how-to-call-superclass-constructor-which-is-hidden/22698543?noredirect=1#comment34586243_22698543
 */
public class Bar extends Foo {

    public static void main(String[] args) {
        Bar bar = new Bar(Arrays.asList(args));
        System.out.println(bar);
    }

    public Bar(List<String> y) {
        super(y);
    }


}

This will compile and run.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top