【问题标题】:Reflection: how to call superclass constructor which is hidden?反思:如何调用隐藏的超类构造函数?
【发布时间】:2014-05-07 01:39:23
【问题描述】:

重新编辑...

我想使用一个被“@hide”Android 标签(或其他标签)隐藏的超类构造函数。

我即将扩展一个已经扩展了两次的类(在 Android 操作系统中)。我想创建自己的子类(即在 Android 操作系统之外)。示例子类,取自 Android 资源:

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);
    }
}

超类如下所示:

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;
    }
}

而我要做的就是制作另一种 WifiP2pServiceInfo,类似于上面的 WifiP2pDnsSdServiceInfo 示例。我不能只继承和调用 super(),因为超类构造函数被 Android 的“@hide”标记,因此对于非系统程序员来说,如果没有反射就无法使用。

所以我的问题是如果我不能通过普通的 super() 调用来访问/调用超类构造函数?反射在这里应该派上用场,但我在 Java 编程方面不是很有经验。

【问题讨论】:

  • 如果A类的编写者将构造函数标记为私有,则表示该类不是为扩展而设计的
  • 在这种情况下,您已经调用了 super()。未定义在同一个对象上调用两个构造函数的结果。
  • 可以在同一个包中定义类。它不必在同一个地方。我假设隐藏意味着它具有default 访问修饰符。
  • 超类构造函数是否标记为protectedprivate?或者什么都没有(这会使它成为包私有的)?
  • @EJP:我很确定在这种情况下子类不会调用 super()。

标签: java android reflection superclass


【解决方案1】:

经过一番研究,我能够自己回答这个问题。

简短的回答:我不能这样做,因为如果超类构造函数被保护并且隐藏,即使我找到了一种如何通过反射调用构造函数的方法,编译器也会抱怨。

长答案:事实证明,“取消隐藏”这些东西并不复杂。关注this tutorial,我可以根据自己的需要扩展课程。

看到了吗?很多噪音都是徒劳的,这就是我一直在寻找的答案。

【讨论】:

    【解决方案2】:

    您想找到该构造函数并将其可用性设置为 true。

    但这是一个危险的操作,您不应轻易尝试。私人不一定意味着私人,这是一个肮脏的秘密,但我仍然希望您尊重课程设计者的意愿而不是规避。

    此外,您不需要这样做。如果我了解您的要求,我已经发布了一个示例,可以满足您的要求。

    这行得通,因为:

    protected修饰符指定该成员只能被访问 在它自己的包中(与 package-private 一样),此外,通过 另一个包中它的类的子类。

    我认为您混淆了受保护修饰符的含义。

    带受保护 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 +
                    '}';
        }
    }
    

    子扩展父:

    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);
        }
    
    
    }
    

    这将编译并运行。

    【讨论】:

    • 我想扩展 Android 的一个类。操作系统已经包含两个子类,我想介绍第三个,用于我自己的协议。因此,我知道 ctor 的签名和所有内容,但我无法弄清楚如何执行此操作的正确语法(此处为 Java 新手)。
    • 什么课?如果它已经包含两个子类,那么这两个子类显然能够在不使用超类的私有构造函数的情况下工作。因此,您可能有一种方法可以在不使用它的情况下编写另一个子类。 ---除非构造函数实际上是包私有的(从原始问题中不清楚)。
    • 请看我编辑的问题,我希望现在更清楚了。很抱歉造成混乱。
    • 新手不应该以这种方式使用反射。
    • 优先组合而不是继承。不要扩展单例。让您的要求更清晰,也许我们可以为下一步提供建议。
    猜你喜欢
    • 2021-09-19
    • 2013-07-19
    • 1970-01-01
    • 2020-07-21
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多