<<4.クラスの基礎の目次
修飾子
問題9(難易度:1)                        2005年4月11日
次の宣言の中で、正しいものを選べ。
        A. final public static char a = 'a';

        B. public b;

        C. abstract int c;
        
    D. public final protected double d;

        E. static private byte e;
        
 
解説
 まずAは、「static」と「final」があるので、aは変更不可の定数になります。変数aはchar型でその値は文字aということになり問題ありません。
 Bは多分intなどの型の指定を忘れたのでしょう。×です。
 Cは「abstract」が問題です。これは抽象クラスや抽象メソッドの指定に使用するもので、変数の宣言には使えません。
 Dはアクセス修飾子の「public」と「protected」がだぶって指定してあるので×。
 Eは特に問題ありません。

解答
 A E

参考 読み物Java 第10章 第17章 第20章
問題10(難易度:1)                                   2005年4月12日
 パッケージpackage1に次のようなクラスAがある。下のクラスのうち、正しいものを選べ。

   package package1;
   public class A {
           int x;
      }
  A. package package1;
     public class B {
             public void methodB() {
                     A p = new A();
                     p.x = 5;
             }
     }

  B. package package2;
     public class C {
             public void methodC() {
                     package1.A q = new package1.A();
                     q.x = 2;
             }
     }

  C. package package2;
     import package1.*;
     public class D {
             public void methodD() {
                     A q = new A();
                     q.x = 2;
             }
     }
解説
 問題はクラスAのインスタンス変数xへのアクセスが、各クラスから可能かどうかです。
 クラスAのインスタンス変数xは、アクセス修飾子の指定がないので、A内のメソッド、及びパッケージpackage1のクラスのメソッドからであればアクセス可能です。クラスBはパッケージpackage1に属するので、問題ありません。

 クラスCは、クラスAとはちがうパッケージpackage2に属するので、「q.x = 2;」としたところでコンパイルエラーになります。クラスDはクラスCをimport文を使って書き換えていますが、これはクラス名の記述上の問題で、アクセスできるかどうかとは関係ありません。

解答 
A

参照 第8章 第10章
問題11(難易度:2)                                  2005年4月14日
 次のようなクラスAがパッケージpackage1にある。下の中からコンパイルエラーになるものを
選べ。

   package package1;
   public class A {
           protected int x;
   }

   A. package package1;
      public class B {
              public void methodB() {
                      A a = new A() ;
                      a.x = 3;
              }
      }

   B. package package2;
      import package1.*;
      public class C extends A {
              public void methodC() {
                      A a = new A();
                      a.x = 3;
              }
      }

   C. import package1.*;
      public class D {
              public void methdD() {
                      A a = new A();
                      a.x = 3;
              }

      }

   D. package package2;
      import package1.*;
      public class E extends A {
              public void methodE() {
                      this.x = 3;
              }
      }

解説
 クラスAのインスタンス変数xのアクセスに関する問題です。xはprotectedの指定なので、次の二通りの場合にはアクセス可能になります。
  @クラスAと同じパッケージpackage1内のクラスからのアクセス
  AクラスAのサブクラスからのアクセス
 まずクラスBは@に当てはまりアクセス可能です。クラスCとEはAのサブクラスなので置いておいて、クラスDはどうでしょう。package文がないので、デフォルトパッケージになり、クラスAとは異なるパッケージになります。よって@にもAにも当てはまらず、コンパイルエラーになります。

 さてAからいくとクラスCもクラスEも大丈夫そうですが、実はクラスCはコンパイルエラーになります。「protected」はサブクラスであれば、別のパッケージ内からでもアクセス可能です。Dのように、継承したx、つまり頭に「this.」がつくものならOKです。(このthis.は省略可能です)クラスCのように、クラスAのオブジェクトのインスタンス変数の場合、いくらprotectedであってもアクセスできません。この辺が他のアクセス修飾子とちがうところなので注意しましょう。ちなみに次はコンパイルエラーになりません。
   package package2;
   import package1.*;
   public class C extends A {
           public void methodC() {
                   C c = new C();
                   c.x = 3;
           }
   }
選択肢とクラス名、解説を書いていてもややこしかったのですが、これも引っ掛け対策と頑張りましょう。
解答
B C

参照 第16章
問題12(難易度:2)                              2005年4月15日
次の二つのクラスについての記述の中で正しいものを下から選べ。

[クラスC]
   package p1;
   public class C {
           protected void methodC() {
                   System.out.println("c");
           }
   }

[クラスD]
   package p2;
   import p1.*;
   public class D extends C {
           public void methodD() {
                   methodC();
           }        
           public static void main(String[] args) {
                   C c = new C();
                   c.methodC();          
           }
   }
   A. クラスCの3行目でコンパイルエラーになる。
   B. クラスDの5行目でコンパイルエラーになる。
   C. クラスDの9行目でコンパイルエラーになる。
   D. コンパイルに成功し、アルファベットのcが出力される。
解説
 メソッドにもアクセス修飾子が付けられます。クラスCのmethodCには「protected」の指定があります。問題11の変数についたものと同じく、次の二通りの場合にはアクセス可能になります。
  @クラスAと同じパッケージpackage1内のクラスからのアクセス
  AクラスAのサブクラスからのアクセス 
 さてクラスDの5行目では、自分がクラスCから受け継いだmethodCを呼び出しているので大丈夫です。この呼び出しの頭には「this.」をつけてもよいですね。 
 ところが9行目ではCのオブジェクトを生成し、それのmethodCを呼び出しているのでコンパイルエラーになります。問題11と同じですね。ちなみにメソッドmainを次のようにするとコンパイルエラーは出ません。
        
        public static void main(String[] args) {
                D d = new D();
                d.methodC();
        }
解答


参照 第16章
問題13(難易度:2)                              2005年4月18日
 二つのクラスがある。クラスAのメソッドmethodAの1行目の下線部分に指定できるものを
下から選べ。

  [クラスA]
   public class A {
                void methodA() {
                   System.out.println("A");                
           }
   }

  [クラスB]
   public class B extends A {
           protected void methodA() {
                   System.out.println("B");
           }
   }

  
  A. private
  B. protected
  C. public
  D. 何も指定しない
解説
 サブクラスのメソッドを上書きする場合、元のメソッドのアクセス指定をより狭める指定はできません。つまりサブクラスBで、methodAのアクセス指定がprotectedになっているので、下線部分はそれより狭いprivateか、何も指定しないか、同じprotectedでなければなりません。もう一度アクセス修飾子のアクセスの範囲が広がる順を確認しておきましょう。

  狭い  private → なし → protected → public  広い

 実は正解のうちどれかひとつを入れた場合、厳密にはクラスAが上書きされる、というわけではないのです。どれだかわかりますか?はてさてこの辺は次の問題で解決しましょう。

解答
A B D

参考 第16章 狭くしないで
問題14(難易度:3)                           2005年4月19日
 二つのクラスがある。クラスAのメソッドmethodAの1行目の下線部分に指定できるものを
下から選べ。

  [クラスA]
   public class A {
                void methodA() {
                   System.out.println("A");
           }
   }

  [クラスB]
   public class B extends A {
           protected void methodA() {
                   super.methodA();
                   System.out.println("B");
           }
   }

  A. private
  B. protected
  C. public
  D. 何も指定しない
解説
 問題13とちがうのは、クラスBのmethodA内に
   super.methodA( );
が追加されたことだけです。

 では下線部分に「private」を入れた場合を考えましょう。このときクラスAのmethodAは、クラスA内でしかアクセスできないことになります。つまりクラスBのmethodA内で、「super.methodA();」とスーパークラスのmethodAを呼び出しても、アクセスが許されていないのでエラーになります。「protected」「何も指定しない」については、同一パッケージ内なのでアクセス可能となり問題ありません。

 さてでは問題13で、下線部分に「private」を入れた場合はなんだったのでしょう。もともとprivate指定のメソッドはサブクラスに継承されません。当然上書きはできません。つまりここでのクラスBのmethodAは、クラスAのmethodAを上書きしたものではなく、単に別のメソッドを定義したものだったんですねぇ。

解答
B D

参考 第10章 第16章
問題15(難易度:3)                               2005年4月20日
 パッケージp1にクラスA、パッケージp2にクラスBがある。クラスAのメソッドmethodAの
1行目の下線部分に指定できるものを下から選べ。

  [クラスA]
   package p1;
   public class A {
                void methodA() {
                   System.out.println("A");                
           }
   }

  [クラスB]
   package p2;
   import p1.A;
   public class B extends A {
           protected void methodA() {
                   System.out.println("B");                
           }
   }

  A. private
  B. protected
  C. public
  D. 何も指定しない
解説
 ああ、しつこいですねぇ。今度は問題13の各クラスが別のパッケージにある場合です。

 下線部分に「private」や「何も指定しない」場合は、別パッケージのクラスBからはアクセスできません。よってクラスB内で定義されたmethodAは、上書きしたものではありませんが別物としてならばOKです。ただし「何も指定しない」場合は警告が出ました。きっとこんな微妙な問題は出ないでしょう。ごめんなさい。

 「protected」は別パッケージのサブクラスからアクセス可能でOK、上書きになります。「public」はサブクラスで「protected」指定のため、アクセスの範囲が狭くなってしまい×です。

解答
A B D

参考 第10章 第16章
問題16(難易度:3)                                2005年4月21日
 パッケージp1にクラスA、パッケージp2にクラスBがある。クラスAのメソッドmethodAの
1行目の下線部分に指定できるものを下から選べ。

  [クラスA]
   package p1;
   public class A {
                void methodA() {
                   System.out.println("A");                
           }
   }

  [クラスB]
   package p2;
   import p1.A;
   public class B extends A {
           protected void methodA() {
           super.methodA();
                   System.out.println("B");                
           }
   }

  A. private
  B. protected
  C. public
  D. 何も指定しない

解説
 ものはついで、問題14の別パッケージ版もやっちゃいましょう。問題15とちがうのは、クラスBのmethodA内の
   super.methodA( );
の追加です。
 これが追加されているということは、上書きをしているということですね。
 まず「private」のメソッドは上書きできません。さらにアクセスできないメソッドも同様です。つまり別パッケージなので「何も指定しない」場合ですね。もちろん「public」はだめ、いいのは「protected」だけです。

 問題13から似たような問題続きで飽きてしまったことでしょう。ざっとまとめるとこんな風になるかな。

 サブクラスでスーパークラスのメソッドを継承または上書きできる大前提は、サブクラスからそのメソッドにアクセス可能である、ということである。上書きについてのアクセス指定の規則は狭くしないこと。(→第16章 狭くしないで)スーパークラスのprivate指定のメソッドと、同じシグネチャのメソッドをサブクラスで定義した場合、上書きではないので(ここでは別物と呼んだりしていました)戻り値の型はちがってもよい。

解答
B

参考 第10章 第16章
問題17(難易度:1)                                 2005年4月22日
次の記述のうち正しいものを選べ。

   A.抽象クラス内の変数はすべて、public static finalの指定が暗黙的になされる。
   B.抽象クラス内のメソッドはすべて、abstractの指定がなくても、抽象メソッドと見なされる。
   C.interface内の変数はすべて、public static finalの指定が暗黙的になされる。
   D.interface内のメソッドはすべて、abstractの指定がなくても、抽象メソッドと見なされる。
   E.抽象メソッドでないメソッドは、抽象クラスには宣言できるが、interfaceには宣言できない。
解説
 抽象クラスとinterface、修飾子についてもごっちゃになりますよね。

 変数にすべて「public static final」の指定が自動的にくっつくのはinterfaceです。またメソッドに「public abstract」の指定が自動的にくっつくのもinterfaceです。とにかく横着した場合コンパイラが自動的にくっつけてくれるのはinterfaceですね。

 interface内には抽象メソッドしか宣言できません。何しろ「abstract」をつけなくても、コンパイラが自動的にくっつけてくれるくらいですから。一方抽象クラスでは、抽象メソッド以外のメソッドも宣言できます。これはサブクラスの共通処理を記述する場合に利用できます。
解答
C D E

参考 第17章
問題18(難易度:1)                            2005年4月25日
クラス(内部クラスを除く)に指定できる修飾子を下から選べ。

 A. public
 B. private
 C. protected
 D. final
 E. abstract
 F. static
解説
  A〜Cはアクセス修飾子です。クラスのアクセス修飾子は「public」を指定すると、どこからでもアクセス可能、何も指定しないと、同一パッケージ内からのみアクセス可能になります。それ以外は指定できません。(→第8章
 「final」の指定されたクラスはサブクラス化できません。(→第16章 サブクラスを作れないクラス)逆に「abstract」が指定されると、抽象クラスになり、そのクラスのオブジェクトを作ることはできず、必ずサブクラス化しなければなりません。(→第17章
 Fの「static」はクラスには指定できません。

解答
A D E
問題19(難易度:1)                               2005年4月26日
 次の下線@Aそれぞれに指定できるものを、下から選べ。

   public class A {
            @  int x;

            A  void methodA() {
            
           }
   }

       A. public
       B. private
       C. protected
       D. final
       E. abstract
       F. static
解説
 @は変数に指定できる修飾子です。A〜Cのアクセス修飾子はどれも指定できます。「final」指定は、変更不可、「static」指定はクラス変数になります。(→第20章)「abstract」は指定できません。

 Aはメソッドに指定できる修飾子です。アクセス修飾子はどれも指定できます。「final」指定は上と同様変更不可で、サブクラスで上書きできません。(→第16章 サブクラスを作れないクラス)それとは逆に「abstract」指定は抽象メソッドになり、サブクラスで必ず上書きしなければなりません。ところがメソッド本体({…}の部分)があり、クラス自体に「abstract」の指定がないので、このクラスは抽象メソッドを含めることができません。ちょっとひっかけだったかな。(→第17章 保育園児よもう一度)「static」を指定するとクラスメソッドになります。(→第20章 Mathの正体

解答
@ A B C D F
A A B C D F
<<4.クラスの基礎の目次次問題>>
Copyright (c) 2004-2005 Nagi Imai All Rights Reserved..