RE: プログラマー面接時の技術的な質問事項

プログラマー面接時の技術的な質問事項(アプレッソ版) : 小野和俊のブログ に回答してみよう。まだ学生だし、たぶん間違えているけど、気にしない。

開発実績編

これまでに携わってきた開発プロジェクトの中で、一番の自信作と言えるものはどんなものですか?

実務経験は無いけど JVM 上で動作する軽量スクリプト言語処理系を作った*1経験がある。実務経験は早いうちに積み重ねたいね。

プログラミング基礎編

for (int i = 0; i < list.getLength(); i++) {}の潜在的パフォーマンスボトルネック

パフォーマンス的には getLength を毎回計算していること。これは list の実装に依存しているけど、例えば File.length() などでこれと同じことすると激遅になる。素直に Iterator 使ったほうが分かりやすいし速くなることも多いと思うよ。
また、パフォーマンス的な話とは異なるけど、ツッコミを入れるならば list の内容がループ中に変更されていたりすると意図した動作とは異なる挙動を示すことがある。

参照渡し/値渡し関係の質問

Java には参照渡しは無い。

switch fall throughなどのうっかりミスが出やすいケースでの問題箇所の指摘

気をつけて貰わなきゃいけないけど、気になるならばラベルの前に assert false: "switch fall through";

オブジェクト指向

クラスとインスタンスの違いの説明

設計図と製品の比喩を使っても良いんだけど、java においてはインスタンスはヒープ上に存在するデータそのもの、クラスはそのデータのフォーマットと挙動を定義するプログラムそのもの。ただし java においてはクラス自体も Class クラスのインスタンスとして同一視されることがある。

インターフェースと抽象クラスをどんな基準で使い分けているか

  1. 子クラスを親クラスと同一視したい場合のみ抽象クラスを用いる
  2. 親となる抽象クラスまたはインタフェイスが機能そのものを表す場合*2にはインタフェイスを用いる
  3. 子となるクラスが既にクラス階層中に組み込まれていて多重継承とせざるをえない場合にはインタフェイスを用いる

継承とコンポジションをどんな基準で使い分けているか

  1. 基本的にはコンポジションを用いる
  2. 子クラスが親クラスと同一視できる場合に継承を用いる
    1. ただし基本的にはクラスではなくインタフェイスの継承で足りるならば*3それを継承しコンポジションを用いる
    2. java.util.AbstractList など差分プログラミングを前提としたクラスに対しては継承を用いる

デザインパターン

Singletonパターンとオブジェクト生成コスト、Singletonパターンのマルチスレッド対応について、注意すべき点を説明してください

Singleton が mutable ならば、メソッド呼び出しを可能な限りアトミックに行えるように努める。

Observerパターンでイベント発火順序が重要な理由を説明してください

Observer パターンにおいてはイベント発火順序を不定であると見なして実装すべき。というよりも各 Observer 間に関係が存在している時点でそれは Observer パターンとは違う何かなんじゃないのかな〜。*4

Mediatorパターンでメソッドが多くなりすぎてきたときにどのような工夫をしますか

各メソッドのうち共通に纏められるものを纏める?

Visitorパターンを使うべき場合と、再帰的ループで対処する場合とを、どのように使い分けますか

再帰的ループで処理する」という動作自体を切り出したいときに Visitor パターンを用いる。

Compositeパターンが時として「オブジェクト指向的に気持ち悪く」なるのは何故ですか

中身と外身を無理に同一視させるような場合が出てくるから?

Java

static/finalの意味

インスタンスではなくクラスに属するメソッド or フィールドが static。メイヤーのオブジェクト指向では static は無いが、ケイのオブジェクト指向ではクラスもオブジェクトなので static が登場する。java が採用したストラウストラップのオブジェクト指向では static が登場するが、これは C++ からの流れ。
final は値が書き換わらないフィールドやローカル変数、または継承してほしくないクラス、またはオーバーライドされたくないメソッドに対して付けられる修飾詞。個人的には public なフィールドは全て final であることが望ましいと思っている。

List/Set/Mapの違い

『(順序付き)リスト』『集合』『キーと値の対応』

new Boolean(true)、new Integer(5)などがあまり推奨されない理由

不要なオブジェクト生成を行ってしまうから。

防御的コピーの話

防御的コピーしなければと思っていても、なんとなく面倒だしボトルネックになりそうだしでなかなか手がつけられない。悪い癖だなぁ。
public List getList() とかだと、ドキュメントに「このメソッドによって返されたリストを変更した場合の挙動は未定義である」と書いてお茶を濁すこともある。

Javaでのディープコピーの実装方法としてどのようなものが考えられますか(普通にclone()を実装、直列化を利用etc.)

clone() の実装って、きちんと行おうとすると物凄く難しかったりする。さらに継承が登場したり、ディープコピーしたいクラスが数種類あったりすると意外と制御が難しいので、『ディープコピー機』クラスを作ることが時々ある。直列化は例外発生しそうでいやん。

バージョンの異なる同一FQNのクラスを利用する必要があるとします。どのような対応方法が考えられますか

クラスローダ自作しちゃっても良いんだけど、デバッグが妙に面倒なので汚染を防ぐ意味でも vm を分ける。通信は tcp/ip で。そういえば RMI とか CORBA とかは使ったことないや。

スレッドプログラミング関係は得意ですか?

スレッド結合度を疎にできるならば俺の足りない脳みそでもなんとかなったりする。単純な非同期実行くらいが関の山かな。Ada 流ランデヴーとかは可能な限り使いたくないなぁ。

*1:作っている

*2:例えば Cloneable, Runnable, Serializable など

*3:例えば java.util.List など

*4:http://blog.livedoor.jp/lalha/archives/50254720.html