有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

继承为什么即使扩展了类,我也不能访问受保护的java方法?

以下是受保护方法的文档:

/** Converts jmusic score data into a MIDI Sequence */
protected  javax.sound.midi.Sequence scoreToSeq(Score score)

我制作了这个小类来扩展scoreToSeq方法的类:

public class MidiSequence extends MidiSynth{

    public Sequence getSequence(Score score){
        MidiSynth synth = new MidiSynth();
        Sequence sequence = null;
        try
        {
                    // Here I get the error saying that the method has
                    // protected access in MidiSynth
            sequence = synth.scoreToSeq(score);

        }
        catch (InvalidMidiDataException e)
        {
            /*
             *  In case of an exception, we dump the exception
             *  including the stack trace to the console.
             *  Then, we exit the program.
             */
            e.printStackTrace();
            System.exit(1);
        }

        return sequence;

    }
}

共 (2) 个答案

  1. # 1 楼答案

    通过这样做:

    MidiSynth synth = new MidiSynth();
    sequence = synth.scoreToSeq(score); 
    

    实际上,您并没有利用扩展MidSynth类这一事实

    如果你想试试的话

    this.scoreToSec(score);
    

    然后您会发现您可以访问受保护的函数

  2. # 2 楼答案

    (编辑:theycallmemorty's answer给出了在您的案例中避免此问题的实用建议。此答案给出了您必须遵循该建议的原因,即语言为何以这种方式设计。)

    您只能访问与访问代码(或子类)类型相同的另一个对象的受保护成员,即使该成员在超类型中声明为

    Java Language Specification, section 6.6.2开始:

    Let C be the class in which a protected member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if Id denotes an instance field or instance method, then:

    • If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.
    • If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

    这是为了允许类型访问与其自身继承树相关的成员,而不会破坏其他类的封装。例如,假设我们有:

         A
        / \
       B   Other
      /
     C
    

    和一个声明为受保护的成员x。如果没有规则的工作方式,您可以通过将一个成员放入Other来完成封装:

    public int getX(A a)
    {
        return a.x;
    }
    

    只需调用BC实例的传递,该成员将有效地成为公共成员,因为您可以通过引入另一个类来解决此问题。。。这不是个好主意。使用当前规则,您必须将BC子类化,而这可能是您首先无法实现的