コンテンツにスキップ

宿題:OO言語1#

OO言語#宿題1

Homework 約30分 答え

Java標準のStringクラスのソースコードを確認し,String内に含まれる以下4種類の要素を探せ.それぞれ4個以上列挙せよ.

  • フィールド(非staticな一般的なフィールド)
  • staticフィールド
  • メソッド(非staticな一般的なフィールド)
  • staticメソッド

以下の書式をコピーして回答せよ.

# フィールドprivate final byte[] value;
???

# staticフィールド???

# メソッド???

# staticメソッド???

回答時にはソースコード内の宣言文1行のみをコピペすること.つまりフィールドの場合は宣言文,メソッドの場合はシグネチャ文が答えである.例えば,String.javaのこの一文は通常のフィールドであり,次のように答えれば良い.

# フィールドprivate final byte[] value;

回答フォーム

Answer

フィールド

  • private final byte[] value;* 文字列の本体データ
  • private final byte coder;* エンコード
  • private int hash;* 内部計算用
  • private boolean hashIsZero; // Default to false;* 内部計算用
  • 上記4つのみ

staticフィールド

  • public static final Comparator<String> CASE_INSENSITIVE_ORDER* 比較用
  • static final byte LATIN1 = 0;* エンコード用
  • static final byte UTF16 = 1;* エンコード用
  • private static final long serialVersionUID = -6849794470754667710L;*
  • private static final char REPL = '\ufffd';* ユニコードの置換文字
  • など
  • この部分はフィールド宣言でもメソッド宣言でもない.フィールドの初期化である)

メソッド

  • public String() {* コンストラクタ
  • public String(String original) {* コンストラクタ
  • public String(char[] value) {* コンストラクタ
  • public int length() {* 文字長の取得
  • public boolean isEmpty() {* 空かの判定
  • public String toUpperCase() {* 大文字への変換
  • など

staticメソッド

  • public static String valueOf(int i) {* int→String変換
  • public static String valueOf(long l) {* long→String変換
  • private static Void rangeCheck(char[] value, int offset, int count) {*
  • private static boolean isASCII(byte[] src) {*
  • など

最低限フィールドとメソッド,及びstaticか否かが判断できるようにせよ.性質が全く異なる要素である.それに加えて以下のような点に気づくと良い.

  • Javaはオープンソースなので直接ソースコードを確認できる
  • String内で保持する文字列データは単なるbyteの配列である
  • Stringには様々なコンストラクタが存在する
  • Stringはかなり複雑である(5,000行)
  • 半分以上がコメントである(約60%)

Q&A#

:口頭での解説はスキップ

誤字#

  • 特にプリミティブ型と参照型の違いには要注意である.者はオブジェクトであるが者はオブジェクトではない.
  • クラスやフィールドの命名規則には共通認識が存在する.Javaにおいては,クラス名は先頭と区切りを大文字~

宿題のメール自動返信はあった方が良いか?#

賛成20,反対5くらいでした.しばらく自動返信をONにします.メールアドレス入力してください.阪大アドレス以外でもOKです.

先週話していたゲームのデバッグ動画ってどれ?#

かなりニッチで万人受けする内容ではないです.

桜井政博の「ゲームを作るには」という動画がおすすめです#

見てみます.

関数の名前の長さに常識はあるか?#

ほぼ好みの問題です.短い方が良いが,短くて混乱するくらいなら長くてもOKです.例のFactorioの動画ではfindMatchingUndergroundInRemovedEntities()というメソッドがありました.

変数名等の命名規則はマナーとのことだが,どの程度重要なのか?#

まつ本の直感的には,土足で部屋に上がるくらい違和感があります.あるいは英語句読点の直後にスペースがないくらい違和感がある.

However,we have to ...

属人性に起因する問題は起きないのか?開発プロジェクトに強い属人性がある場合,特定の開発者に責任が偏らないか?#

👍👍👍

これはよくある問題です.オープンソースプロジェクトでよく起きます.開発プロジェクトの人的側面に着目した研究もたくさんあります.

他者の作成したクラスを再利用する仕組みはあるのか?うまい検索方法はあるのか?#

👍👍👍

ライブラリ(クラスの集合)単位の検索の仕組みはあります.ただクラス単位での再利用は現状うまくいっていません.研究自体はたくさんあります.

Javaにおいてクラス内のフィールドは遡っていくと最終的にプリミティブ型だけで構成されている?#

👍👍👍 これは良い質問.

考えたことなかったけどたぶんYes.データの元を辿っていくと常にプリミティブ型にたどり着くはず.

プロDと説明が食い違っている.どちらが正しいのか?#

               クラス(型・設計図)
Stack stack = new ArrayStack();
    インスタンス(実体)

上記の図に対してプロDでは右辺がインスタンス,左辺がその参照とあった.

これは視点の違いの問題です.両方正しいです.

ソースコードを静的な側面で見た場合,つまり「構文の各要素の意味」を考えた場合;

               "ArrayList" はクラス(型・設計図)
Stack stack = new ArrayStack();
    "stack" はインスタンス(実体)

ソースコードを動的な側面で見た場合,つまり「代入文の実行結果」を考えた場合;

Stack stack = new ArrayStack();
      ~~~~~   ~~~~~~~~~~~~~~~~ 
        ↑     newによるインスタンス生成    右辺インスタンスへの参照を格納

C言語とJavaで定数の表現がなぜ異なるのか?C言語は#define,Javaはfinalで別物に見える#

正確にはC言語の定数はconstです.キーワードが違うだけでほぼ同じ利用方法です.

  • C言語:const double PI = 3.14;
  • Java:final double PI = 3.14;

#defineはマクロ宣言と呼ばれていて,直感的には「コンパイルの直前にdefineされたキーワードをすべて置換する」という処理が適用されます.

#define PI 3.14
...
double circumference = 2 * PI * radius

↓マクロの展開(コンパイル直前に置換される)

...
double circumference = 2 * 3.14 * radius

プロトタイプベースとクラスベースの利点欠点は?#

プロトタイプベースのほうが柔軟だが固さがないので予期しにくい.クラスベースはその逆.

型あり型なしの違いによくにている気がする.柔軟さが生む利点と欠点の話.

PythonとJavaで命名規則のルールが違う理由は?#

文化やコミュニティが違うからです.

グローバル変数の数は少ない方が良いのか?#

引数や戻り値で行ったり来たりするよりグローバル化したほうが良いのでは?

"Global Variable Considered Harmful"です.グローバルは極力減らすべき.特に可変なグローバル変数は絶対にやめた方が良い.誰がいつ変更したか予測できないためです.「参照透過性」や「副作用」という概念を調べると良い.

なぜJavaにはプリミティブ型のラッパークラスが存在するのか?#

プログラム中のあらゆる要素をオブジェクトとして表現できるからです.また,ジェネリクスの部分にプリミティブは指定できません.

List<Integer> list = ... // OK
List<int> list = ...     // NG

プリミティブ型の存在以外にJavaがOOの原則に則っていない部分はある?#

関数自体もオブジェクト(第一級オブジェクト)ではありません.

(前回Q&Aより)なぜ何種類もプログラミング言語があるのか?1つに統合してよいのでは?#

面白い画像を見つけてきました.

How standards proliferate (なぜ標準が増殖するのか)


再来週が中間試験です#

講義概要#試験に必ず目を通すこと.鉛筆消しゴムは必須です.今年(2025)は過去問(2024)と範囲が違う点に注意.

配属される研究室による就職実績,企業からの推薦の量,業界分野の差はありますか?#

就職は個人の戦いだと思った方がよい.少なくとも楠本研と肥後研では斡旋はやっていない.ほかの研究室も同じだと思う.研究室の教員より先輩の方が役に立つかも.

大学院への飛び級制度を検討するうえでの注意点等はあるか#

授業についていけない等なければ,積極的に狙ってよいと思う.少なくとも生涯年収1年分 + 授業料1年分が得になる.研究期間は2年と短くなる点には注意.研究室見学に行くとよい.

進学するか就職するか決めきれず迷っています#

研究室見学にいこう.

コンストラクタが複数定義されるのは違和感がある#

複数コンストラクタはOOの典型かつ実践的なパターンなので覚えておくとよい.

2Dグラフィックス系の処理において,円というオブジェクトを設計してみよう.円は中心座標x yと半径radiusの3つのフィールドで表現できる.円インスタンスの作成はnew Circle(0, 0, 10);としたい.

public class Circle {
    int x;
    int y;
    int radius;
    public Circle(int x, int y, int radius) {
        this.x = x;  // (1)!
        this.y = y;
        this.radius = radius;
    }
    ...
}
  1. thisは自分自身のインスタンスを示すキーワード.フィールド名と変数名が重複しているのでthisが必須.

状況によっては,半径の指定をサボりたい場合がある.半径10を何度も生成するなど.この場合new Circle(0, 0);のようにコンストラクタを呼び出したい.2つ目のコンストラクタを追加しよう.半径のデフォルト値はひとまず10にしておこう.

public class Circle {
    ...
    public Circle(int x, int y) {
        this.x = x;
        this.y = y;
        this.radius = 10;
    }
}

中心座標ですらデフォルト値0 0で埋めたい,という状況があるなら次のように拡張する.new Circle()で円を作成できる.

public class Circle {
    ...
    public Circle() {
        this.x = 0;
        this.y = 0;
        this.radius = 10;
    }
}

まとめると以下の通り.円作成の状況に応じて3つのコンストラクタを提供しておく.

public class Circle {
    public Circle(int x, int y, int radius) {
        this.x = x;  this.y = y;  this.radius = radius;
    }
    public Circle(int x, int y) {
        this.x = x;  this.y = y;  this.radius = 10;
    }
    public Circle() {
        this.x = 0;  this.y = 0;  this.radius = 10;
    }
}

最後にリファクタリングすると以下の通り.フィールドへの代入という処理が最上部のコンストラクタのみに集約される.

public class Circle {
    public Circle(int x, int y, int radius) {
        this.x = x;  this.y = y;  this.radius = radius;
    }
    public Circle(int x, int y) {
        this(x, y, 10);  // ↑のコンストラクタを呼び出す
    }
    public Circle() {
        this(0, 0);      // ↑のコンストラクタを呼び出す
    }
}