当前位置: 首页 > 知识库问答 >
问题:

Java在子类的复制构造函数中使用超类的保护方法

长孙鸿
2023-03-14

我有一个受保护的方法(我不希望在超类或子类之外看到此方法)。我想在复制构造函数中使用它,但我不能。法典:

public class Superclass {
    protected HashMap<Object, Object> getData() {
        return new HashMap<>();
    }
}

public class Subclass extends Superclass {
    public Subclass(Superclass abstractClass) {
        init(abstractClass);
    }

    private void init(Superclass abstractClass) {
        //ERROR!!! getData has protected access in Superclass
        for (Map.Entry<Object, Object> entry : abstractClass.getData().entrySet()) {
            //do something
        }
    }
}

如果我仍然想在不公开 getData() 方法的情况下从超类对象创建子类对象,我该如何克服这个问题?

编辑类在不同的包中!

共有3个答案

杭胜
2023-03-14

从不同包中的类访问受保护的方法是不可能的-请参见http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html.您从Superclass继承的事实不算数,因为您尝试在对Superclass的引用上调用该方法,而不是在基类本身上调用该方法。

因此,您试图做的事情是行不通的——如果行不通的话,它会破坏Java的访问控制:您可以简单地从任何类继承并实现一个以超类引用为参数的方法,然后访问超类的所有受保护方法(当然,您仍然可以从基类继承并访问超类中受保护的成员,甚至跨包)。

如果< code>getData()是一个需要从另一个包中调用的方法,您需要将其公开。

附带说明一下,您可能应该重新考虑您的设计 - 是否真的有必要在 Subclass 构造函数中传递对超类对象的引用?

晏弘雅
2023-03-14

在同一个包中,以下内容对我来说效果很好:

超类:

public class Superclass {
    protected List<String> getData() {
        return Arrays.asList("a", "b", "c");
    }
}

亚纲:

public class Subclass extends Superclass {

public static void main(String[] args) {
    Superclass superObject = new Superclass();
    Subclass subObject = new Subclass(superObject);
}

    public Subclass(Superclass abstractClass) {
        //ERROR!!! getData has protected access in Superclass
        for (String entry : abstractClass.getData()) {
            System.out.println(entry);
        }
    }
}

请注意,我不确定这是你真正想要做的。例如,为什么要在< code>Subclass的构造函数中传递< code>Superclass的实例?此外,您有一个< code>HashMap而不是< code>List,但是HashMap不是< code>Iterable,所以您不能对它们使用扩展的for循环

但是:如果这些类在不同的包中,事情就会发生变化。查看语言规范;在§6.6.1中它说:

[一] 如果成员或构造函数被声明为受保护,则仅当以下情况之一为真时才允许访问:

>

  • 从包含声明受保护成员或构造函数的类的包中访问成员或构造函数。

    访问是正确的,如 §6.6.2 中所述。

    §6.6.2规定:

    对象的受保护成员或构造函数可以从包外部访问,其中它仅由负责该对象实现的代码声明。

    现在,由于在init方法中调用函数并不被认为是负责实现的,所以您可能无法在这里访问成员。抱歉,语言就是这样的。

  • 施振海
    2023-03-14

    在创建实例之前,您尝试访问某个方法。实例尚未完全初始化。

    调用从自己的构造函数构造的对象的方法可能会导致意外的行为,因为在构造函数完成之前,对象不会一致初始化。

     类似资料:
    • 问题内容: 我正在尝试创建一个将字段作为参数的构造函数,然后将其放入存储在超类中的字段中。这是我正在使用的代码 在超类中,我用 我有一个访问器方法 我收到一个错误“ 味道在超类中具有私有访问权 ”,但是我认为这无关紧要,因为我正在调用将其返回到字段的访问器方法? 问题答案: 您应该做什么: 在您的超类中添加一个构造函数: 在Crisps类中: 注释 对您的问题的一些评论: “在超类中,我已经用”

    • 为什么第一个输出有柱线 = 空?是因为在创建类 B 之前调用了 B.foo() 吗?如果是,那么为什么可以调用 B.foo()?还是因为 B.foo() 中的字段栏试图从 A 获取柱线字段但无法访问它? 我的问题与链接的问题不同,我不是在问调用顺序,我是在问为什么第一个输出为空?另一个问题不是关于字段或空变量。 我不明白B.foo中的bar变量是如何为空的,如果它是在A和B中定义的。

    • 问题内容: 我有一个“ ChildClass”类,它扩展了“ ParentClass”类。我不想完全替换父类的构造函数,而是要先调用父类的构造函数,然后再做一些额外的工作。 我相信默认情况下会调用父类的0参数构造函数。这不是我想要的 我需要用参数调用构造函数。这可能吗? 我试过了 但这不起作用,因为您无法修改“ this”。 问题答案: 您可以从子代的构造函数中以“ super”引用父代的构造函数

    • 问题内容: 编译该程序时,出现错误- 错误-找不到构造函数Person()。为什么定义Person()是必要的? 问题答案: 创建时,您要同时创建一个。为了确保构造正确,编译器在构造函数中添加了一个隐式调用: 由于没有无参数构造函数,因此失败。 您可以通过以下任一方式解决它 添加对super的显式调用,如下所示: } 或通过将no-arg构造函数添加到: } 通常,编译器还会隐式添加无参数构造函数

    • 问题内容: 考虑以下代码 在我看来,目前有两种方法可以避免这种问题。 要么上A班最后一班。 要么 使getVar方法最终化 作者试图提出防止上述问题的方法。但是,该解决方案似乎很麻烦,因为要遵循一些规则。 http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a- superclass-constructor/ 除了

    • 我见过子类的构造器方法被用于具有超类类型的变量。例如: 是类型对象还是类型?由于类inherit from,因此它的方法可能比它的超类多。实例调用这些函数是否只能存在于中,而不能存在于中?在这种情况下,和可以互换吗?例如: