質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • Java

    16766questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    7622questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Java(Android)の文法で意味が分からない部分があります

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,460

zico_teratail

score 465

Android開発の入門書を読んでいて、理解不能なコードがありましたので質問します。
※おそらくJavaの基礎文法がまだ分かっていないために理解不能なのだと思います。

MainActivity内にてオーバーライドしたonCreateの中で、以下のようなコードがあります。
TextView tv = (TextView) this.findViewByID(R.id.textview1);
上記の(TextView)の部分の意味が分かりません。
メソッド名の後に()が来るなら分かりますが、いきなり()で、その後も普通にthisが続くという表記の意味が理解できません。

たとえば、
TextView tv = new TextView();
というコードでしたら、
「tvという変数にTextView型のクラスのインスタンスを生成して入れる」
と言葉で表現できます。(合ってます・・・よね?)

同じように前述のコードを言葉・文章で表現すると、どのようになりますでしょうか?
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

checkベストアンサー

+7

Activity#findViewById()はView型のインスタンスを返却します。ViewはButtonやTextViewなどのスーパークラスです。そのためTextViewの参照変数に代入するにはダウンキャストをしてあげる必要が出てきます。

ダウンキャストをする理由として、Androidでは一般的にレイアウトをxml、処理をJavaコードで書きます。そのため、xmlで作られたView群とコード内のViewインスタンス群を関連付ける必要があります。xmlとJavaコードの糊付けとしてidとfindViewById()を使用します。

本来であれば戻り型をそのまま使えるようにすればいいのですが、xml内では自作のViewも追加することがあります、そうすると戻り型が特定する方法が難しくなるのでプログラマの責任でキャストをする必要があるのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/11 01:36

    個人的には、今回の質問内容の要点はJavaとxmlを組み合わせてレイアウトを簡潔に記載しようとし、Javaのリフレクション技術を使った。そのため、一時的にオブジェクト指向が損なわれている箇所だと思います。

    あくまでもJavaはオブジェクト指向的実装を行うための道具です、ここを理解しそこなうと今後に響きます。注意してください。オブジェクト指向の方針の一つで「動的束縛」というものがあります。多態性に関わってきますので是非理解してください。

    キャンセル

  • 2015/09/11 12:02

    お話がちょっと高度すぎて私の頭ではまだチンプンカンプンですが、要するに「Javaらしくない書き方である」というような意味でしょうか?

    しかしAndroid開発についていろいろ調べていると、「全てをJavaで記述するのではなく、レイアウトはxmlを使うべき。Android Studioもその方向で進化してる」みたいな意見が多数派のようにも見えます。Android特有の事情があるのかもしれませんが、この辺についてyona様はどうお考えでしょうか?

    キャンセル

  • 2015/09/11 12:26 編集

    書き方が悪かったですね。

    Java:動的なものを記述する。処理やデータ、設定で見た目が変わるもの、クリック等のタッチイベントも含む。
    xml:静的なものを記述する。初期レイアウトや色、文言、値などの不変なものを記述する。

    今回の質問ではxmlとJavaが連携する時にxml側から型についての情報が充分には渡せないためキャストが必要と回答しました。

    xmlは積極的に使うべきです。簡潔に記述できます、更に言えば、idと型について事前に打ち合わせをしておけば「見た目を作る」と「処理を作る」を分業することができます。

    キャンセル

+2

他の方がおっしゃるように、その括弧はキャストです。
findViewByIDは、様々なViewを一元管理するために戻り値がViewになっています。例えそれがTextViewのインスタンスだっとしても、そのままではTextView固有のメソッドなどが使えません。なのでキャストが必要になります。

このとき、TextViewViewを継承しているという親子関係から、ダウンキャストとなります。
Javaを含む多くの言語で、ダウンキャストは明示的に行う必要があるため、そのような文法になっています。

「固有のメソッドが使えないから」と書きましたが、実際は可読性のことなども踏まえて、固有メソッドを使おうが使わまいが、キャストするのが一般的となっています。

例として、Buttonの一派的な使い方は以下のような感じですが、
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // ボタンが押されたときの処理
    }
});
setOnClickListenerButton固有のメソッドではなく、Viewに実装されているものを継承により引き継いでいる、あるいはオーバロードしているものなので、キャストしなくても動きます。
View button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // ボタンが押されたときの処理
    }
});
ですが、可読性が損なわれますし、前者(キャストする)の方が一般的です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/11 01:14

    あ、もう一つ追加ですみません。
    setContentView(R.layout.main);
    が出てきたのはActivityを拡張したクラス内のonCreate()内なのですが、
    super.setContentView(R.layout.main);
    とか、
    this.setContentView(R.layout.main);
    などではなく、
    setContentView(R.layout.main);
    だけで良いというのはどういうルールなのでしょうか?

    superやthisを付けなければならない場面と省略できる場面の違いや使い分けがイマイチわかりません。

    キャンセル

  • 2015/09/11 01:18

    Javaにおいてあるクラス内でメソッド名だけ書かれた場合,その対象は「自分自身」です.
    いまこの画面を構成するにあたってActivityのサブクラス(現在このコードを書いているクラス)のインスタンスを生成していますが,このインスタンス自身を指します.その場合「オブジェクト名.」は省略されます.
    あえて書くなら「this.setContentView(R.layout.main)」になるでしょうか.

    >また、setContentViewが行ったというインスタンス化の結果は、具体的にはどの変数に格納されているのでしょうか?
    Activityか,その親クラスのどこかの変数に格納されると思われます.
    先のドキュメントの継承関係でActivityの段階ですでに4段階ほど継承しています.
    その中のどこかで定義された変数に入ることになると思います.
    もっとも,我々はそれを具体的に知る必要はありません.
    それを取り出すためのメソッドとしてfindViewByIDなどが用意されているので.

    キャンセル

  • 2015/09/11 01:23

    >super.setContentView(R.layout.main);
    >とか、
    >this.setContentView(R.layout.main);
    >などではなく、
    >setContentView(R.layout.main);
    >だけで良いというのはどういうルールなのでしょうか?
    どれでも構いませんが.あえてsuper.やthis.などを書く必要がないのです.
    super.は,もしこのサブクラスでsetContentViewをオーバーライドしていた場合,
    「スーパークラスで定義したsetContentViewを使いたい」という場合に使います.
    この場合でsuper.を省略してしまうと,オーバーライドしたメソッドが起動してしまうためです.
    this.は,例えばもう一つ別のActivityオブジェクトが存在し,「どっちのメソッドを使っているのか」を明示したい場合に使います.
    今回の場合はそのどちらも使う必要が無いので,単にsetContentViewとしているのです.

    キャンセル

+1

こんにちは。

これは「キャスト」といって、()内に指定したクラスの型にする という意味があります。
おそらく、findViewByID() メソッドの戻り値が Object型 か何かなのではないですか?

TextView tv = (TextView) this.findViewByID(R.id.textview1);
この場合、
findViewByID( R.id.textview1 ) で取得したインスタンスを TextView型 にして
変数 tv に格納しています。

ちなみに、thisがメソッドの前についていますが、これは
 findViewByID() がこの処理を記述しているクラスのインスタンスメソッドだからです。

TextView tv = new TextView;
これは誤りです。
コンストラクタはメソッドのようなものなので、
TextView tv = new TextView();
と() がないとエラーになります。


投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/09 13:50

    ありがとうございます。

    findViewByID() メソッドの戻り値についてググったところ、
    http://www.javadrive.jp/android/xml_layout/index6.html
    にて、
    > Activityクラスで定義されているfindViewByIdメソッドを使用します。
    > 引数にリソースIDを指定すると、対応するビューのオブジェクトを返します。
    > 実際に使用する時は戻り値をそのビューのクラスでキャストして下さい。

    と書いてありました。
    しかし「ビューのクラスでキャスト」と言われても、なぜそうするのか腑に落ちません。

    そもそも「オブジェクト型をキャストする」という概念がなかなか理解できません。
    これがたとえば「stringをintにキャストする」ならば直感的に意味が理解できます。
    「文字列としての1を、計算できる数字の1に変換して扱うんだな」って直感的に理解できる。

    でもオブジェクト型をキャスト・・・っていう概念が全くわかりません。
    どう理解したら良いでしょうか?

    キャンセル

  • 2015/09/09 15:11 編集

    オブジェクト型のキャストを理解するには、クラスの親子関係についてわかる必要があると思います。
    ↓こちらのサイトなど、
    javaの基本をまとめてくれているサイトはいろいろあるので
    一度見てみるといいかもしれませんね。
     Javaの道:クラス (http://www.javaroad.jp/java_class2.htm)

    ---
    あと、String型はint型にはキャストできません。
    Javaには「オブジェクト型(参照型)」と「プリミティブ型(基本型)」というものがあります。
    ↓こちらのサイトがわかりやすい・・・かな?
     Javaのプリミティブ型と参照型について(http://promamo.com/?p=2818)

    ちなみにStringはオブジェクト型、intはプリミティブ型です。
    オブジェクト型⇔プリミティブ型 に変換するには、"ラッパークラス"という
    プリミティブ型をオブジェクト型として扱うことができるクラスを使う必要があります。

    キャンセル

  • 2015/09/11 00:52

    >String型はint型にはキャストできません。

    PHPで言うところのstringをintにキャスト・・・と同じつもりでいましたが、Javaではそれに該当するのはcharとintであり、Stringはオブジェクト型なんですね。

    へっぽこPHPerの常識ではなかなか理解するのに苦労しました。というかまだ理解しきれていませんが、とにかくオブジェクト型とプリミティブ型という違いがあるのだということは分かりました。

    キャンセル

+1

まずは,継承とキャストについて知る必要があると思います.
このページの「5.1.2 参照型の変換」を読んでください.
以下は,それを踏まえた上で読んでください.

このページは,AndroidのTextViewについてのドキュメントです.注目して欲しいのはここです.
java.lang.Object
   ↳    android.view.View
        ↳    android.widget.TextView
これは継承関係を示しています.TextViewはViewクラスを継承しているので,TextViewのオブジェクトはViewオブジェクトとしても扱うことができます.
一方,メソッドfindViewByID(int)はView(として扱われるオブジェクト)を返します.この返り値はこのままで使えるのはViewクラスのメソッドのみで,TextViewクラスのメソッドは使えません.例え実体がTextViewだとしても,今この返り値が見ているデータの領域はViewの領域のみであるためです.
そこで,キャストによりこのViewをTextViewとして扱えるようにしているのです.(もちろん,対象のオブジェクトがTextViewに関係のないオブジェクトの場合はTextViewとして扱えないので,例外を投げます.)こうすることで初めて,このオブジェクトに対してTextViewのメソッドが使えるようになるのです.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/11 00:29

    「5.1.2 参照型の変換」を読みましたが、難解すぎて理解できません・・・。

    しかしswordone様のご説明は分かりやすく、(本当に私が理解できているかどうかはともかく)納得ができてきました! ありがとうございます。

    キャンセル

  • 2015/09/11 12:48

    リンクでのColorExはColorの情報・機能を確実に持っているので,Color型の変数として扱えます.確実に成功する変換なので代入の際に明示的なキャストは不要です.
    しかし逆に,Color型は必ずしもColorExの情報を持っているとは限りません.ColorExの情報・機能を使うために,その型に変換する必要があるのです.この型変換は確実には成功しないリスクが存在するので,明示的にキャストする必要があります.

    キャンセル

0

おそらくキャストだと思います。こちらをご覧になってはいかがでしょうか。
キャストについてはこちらをご覧になってはいかがでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/09 13:45

    ありがとうございます。
    リンク先を読み、キャストしているということは理解しました。

    しかし、「オブジェクト型をキャストする」という概念がなかなか理解できません。
    これがたとえば「stringをintにキャストする」ならば直感的に意味が理解できます。
    「文字列としての1を、計算できる数字の1に変換して扱うんだな」って直感的に理解できる。

    でもオブジェクト型をキャスト・・・っていう概念が全くわかりません。
    どう理解したら良いでしょうか?

    キャンセル

  • 2015/09/09 15:18

    Stringからintへは「キャスト」できません.
    それは文字を数値に「解析」してるのであって,キャストではありません.
    数値を表すプリミティブ型同士(int⇔longなど)はキャストですが.

    オブジェクト型(参照型)のキャストを理解するためには,まずは「継承」について理解しないといけません.おそらく継承が何かわかっていないのではないでしょうか?

    キャンセル

  • 2015/09/11 00:55

    継承については一応わかっていたつもりですが、今回質問したコード中にあるようなキャストが必要になる場合における継承の影響は、yona様の回答でなんとなく理解できた気がします。

    とにかくOOPに不慣れな者からすると、「オブジェクト型」という概念をナチュラル感覚で理解するのは非常に難しいです。

    キャンセル

-1

変数の「宣言」と「代入」を分けて説明していきます。

まず「宣言」から。
コピペでやったので意識が薄いと思いますが、
TextView tv = ...
っていうのは「後続の処理でTextViewのオブジェクトをtvという変数名で使いたい」って意図で記述している事になります。

で、ではtvのオブジェクトはどうやって生成するかって話になりますが、
それが「代入」です。
TextViewのコンストラクタで設定するのみのオブジェクトであれば、確かにTextViewをnewしてインスタンス生成すれば良いかもしれません。
しかし、ブラックボックス的な情報が詰まったものでないと、恐らく後続の処理は動いてくれないでしょう。
それで、そのブラックボックス的なものというのが、親クラスで定義している「 this.findViewByID(R.id.textview1)」っていう関数の戻り値という事になります。(これはTextViewの設計者の設計によるものなので、このクラスについてはそういう使い方のものだと鵜呑みにしてください。)
さて、そこで問題となるのが、findViewByIDの戻り値の型です。これが「View」であって「TextView」ではありません。
なので、何らかの形でView→TextViewに変換してあげないといけません。
そこで、ネットを検索すると、TextViewはViewのサブクラスということがわかります。
ここから、findViewByIDの戻り値をTextViewでキャスト対応可能ということがわかります。
そこで「(TextView) this.findViewByID(R.id.textview1);」という右辺になるのです。
これが、親子関係にないクラスであれば、必要なプロパティだけ手書きで設定しなければいけないという煩わしいことになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Java

    16766questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    7622questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。