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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

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

Android

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

Q&A

解決済

6回答

7228閲覧

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

zico_teratail

総合スコア907

Java

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

Android

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

0グッド

1クリップ

投稿2015/09/09 04:08

編集2015/09/09 04:10

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

MainActivity内にてオーバーライドしたonCreateの中で、以下のようなコードがあります。

java

1TextView tv = (TextView) this.findViewByID(R.id.textview1);

上記の(TextView)の部分の意味が分かりません。
メソッド名の後に()が来るなら分かりますが、いきなり()で、その後も普通にthisが続くという表記の意味が理解できません。

たとえば、

java

1TextView tv = new TextView();

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

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

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ベストアンサー

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

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

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

投稿2015/09/09 04:42

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zico_teratail

2015/09/09 04:56

詳しい解説ありがとうございます! 私には難しすぎてまだまだ全く理解しきれていませんが、yona様のご説明のおかげで少しずつ頭の中で知識の断片がつながってきた気がします。 オブジェクト指向って難解なんですね・・・
yona

2015/09/09 06:41

キャストについて説明します。 View ・機能1:画面に表示機能群 TextView(Viewのサブクラス) ・機能1:画面に表示機能群(Viewから継承した機能) ・機能2:文字列の表示機能群 View#機能1とTextView#機能1に注目してください。このTextView#機能1とはView#機能1を自分のものとして利用しています。(もちろん機能を追加していたりしていますが) つまり、TextViewはTextViewのインスタンスの中にはViewのインスタンスである部分があります。そのため下記のようなことができます。 TextView textView = new TextView() View view = textView これをリスコフの置換原則といいます。 さて回答から、findViewByIdはとりあえずViewインスタンスを返します。しかしこのインスタンスはTextViewかもしれないし、Buttonかもしれない、その他のViewクラスかもしれない。知っているのはプログラマだけという状態になってしまいます。 このままだとTextView#機能2は使えません。そこで、プログラマの責任でインスタンスに対して、「お前はTextViewなんだよ」と思い出させる行為を取ります、これをダウンキャストと言います。 もちろん違う型を対してキャストしてしまうと例外が発生しますが、これはプログラマが無責任なキャストをしたためです。
zico_teratail

2015/09/10 15:47

なるほど! 点と線がつながってきました! Androidのクラス階層図を見ていたら、そもそもButtonやTextviewは元を辿ればViewを継承してきているんですね。そこに気付いた時点で、yona様や他の皆様のご説明が理解できてきました。 今までPHPのみの経験でJavaは初、しかもPHPでもオブジェクト指向の勉強を避けてきたのでかなり苦しみましたが、Java(というかAndroid?)特有の継承について理解するにつれ、少しずつですが霧が晴れてきました。
yona

2015/09/10 16:36

個人的には、今回の質問内容の要点はJavaとxmlを組み合わせてレイアウトを簡潔に記載しようとし、Javaのリフレクション技術を使った。そのため、一時的にオブジェクト指向が損なわれている箇所だと思います。 あくまでもJavaはオブジェクト指向的実装を行うための道具です、ここを理解しそこなうと今後に響きます。注意してください。オブジェクト指向の方針の一つで「動的束縛」というものがあります。多態性に関わってきますので是非理解してください。
zico_teratail

2015/09/11 03:02

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

2015/09/11 03:27 編集

書き方が悪かったですね。 Java:動的なものを記述する。処理やデータ、設定で見た目が変わるもの、クリック等のタッチイベントも含む。 xml:静的なものを記述する。初期レイアウトや色、文言、値などの不変なものを記述する。 今回の質問ではxmlとJavaが連携する時にxml側から型についての情報が充分には渡せないためキャストが必要と回答しました。 xmlは積極的に使うべきです。簡潔に記述できます、更に言えば、idと型について事前に打ち合わせをしておけば「見た目を作る」と「処理を作る」を分業することができます。
guest

0

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

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

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

例として、Buttonの一派的な使い方は以下のような感じですが、

Java

1Button button = (Button)findViewById(R.id.button); 2button.setOnClickListener(new View.OnClickListener() { 3 @Override 4 public void onClick(View v) { 5 // ボタンが押されたときの処理 6 } 7});

setOnClickListenerButton固有のメソッドではなく、Viewに実装されているものを継承により引き継いでいる、あるいはオーバロードしているものなので、キャストしなくても動きます。

Java

1View button = findViewById(R.id.button); 2button.setOnClickListener(new View.OnClickListener() { 3 @Override 4 public void onClick(View v) { 5 // ボタンが押されたときの処理 6 } 7});

ですが、可読性が損なわれますし、前者(キャストする)の方が一般的です。

投稿2015/09/09 05:04

shiolier

総合スコア1156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zico_teratail

2015/09/10 15:41

ありがとうございます。 >例えそれがTextViewのインスタンスだっとしても 上記のご説明を読んでハッと気付いたのですが、そもそも変数 tv は new(インスタンス化)されてないですね。それなのに行頭に Textview とあるので、Textview型のオブジェクトにさせられようとしている・・・その辺と後のキャストが関係している、という理解でいいのでしょうか?
swordone

2015/09/10 15:48

インスタンス化は,この前に書かれているであろうsetContentViewで行われています. このメソッドは,レイアウトを記述したXMLを読み込んで画面を構成するものです. なので,このメソッドが実行された時点でTextViewを含む画面構成のパーツは出来上がっているのです. findViewByIDはそうして出来上がったパーツを取ってくる,というだけの話なのです.
zico_teratail

2015/09/10 16:01

> swordone様 たしかに前の行に setContentView(R.layout.main); という記述がありました! しかし私はその行も意味が理解できませんでした。 ・setContentViewっていきなり出てきたけど、どのクラスのメソッドなの?? ・戻り値を格納する変数が指定されてないけど、どこに戻り値が入るの? と思い、チンプンカンプンです。
swordone

2015/09/10 16:06 編集

・setContentViewっていきなり出てきたけど、どのクラスのメソッドなの?? Activityクラスのメソッドです.→http://developer.android.com/reference/android/app/Activity.html#setContentView(int) ・戻り値を格納する変数が指定されてないけど、どこに戻り値が入るの? 戻り値はありません(void).Activityが支配する画面にパーツをセットするという「作業」を担うメソッドです.
zico_teratail

2015/09/10 16:11

>Activityクラスのメソッドです そういう説明って、どの入門書を読んでも書いてなくて、いきなり前提知識無しにサラッとコードが出てくるので初学者は混乱しております。 「クラス名.メソッド名()」という形が基本です!とか書いたあとにいきなりそれだったりしますからね・・・。 また、setContentViewが行ったというインスタンス化の結果は、具体的にはどの変数に格納されているのでしょうか? >戻り値はありません(void) こちらは理解できました。 たぶんAPIガイドの該当メソッドを調べればそのこと(voidとか)が書いてあるのですね。
zico_teratail

2015/09/10 16:14

あ、もう一つ追加ですみません。 setContentView(R.layout.main); が出てきたのはActivityを拡張したクラス内のonCreate()内なのですが、 super.setContentView(R.layout.main); とか、 this.setContentView(R.layout.main); などではなく、 setContentView(R.layout.main); だけで良いというのはどういうルールなのでしょうか? superやthisを付けなければならない場面と省略できる場面の違いや使い分けがイマイチわかりません。
swordone

2015/09/10 16:18

Javaにおいてあるクラス内でメソッド名だけ書かれた場合,その対象は「自分自身」です. いまこの画面を構成するにあたってActivityのサブクラス(現在このコードを書いているクラス)のインスタンスを生成していますが,このインスタンス自身を指します.その場合「オブジェクト名.」は省略されます. あえて書くなら「this.setContentView(R.layout.main)」になるでしょうか. >また、setContentViewが行ったというインスタンス化の結果は、具体的にはどの変数に格納されているのでしょうか? Activityか,その親クラスのどこかの変数に格納されると思われます. 先のドキュメントの継承関係でActivityの段階ですでに4段階ほど継承しています. その中のどこかで定義された変数に入ることになると思います. もっとも,我々はそれを具体的に知る必要はありません. それを取り出すためのメソッドとしてfindViewByIDなどが用意されているので.
swordone

2015/09/10 16:23

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

0

まずは,継承とキャストについて知る必要があると思います.
このページの「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/09 05:05

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zico_teratail

2015/09/10 15:29

「5.1.2 参照型の変換」を読みましたが、難解すぎて理解できません・・・。 しかしswordone様のご説明は分かりやすく、(本当に私が理解できているかどうかはともかく)納得ができてきました! ありがとうございます。
swordone

2015/09/11 03:48

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

0

こんにちは。

これは「キャスト」といって、()内に指定したクラスの型にする という意味があります。
おそらく、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 04:17

kaputaros

総合スコア1844

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zico_teratail

2015/09/09 04:50

ありがとうございます。 findViewByID() メソッドの戻り値についてググったところ、 http://www.javadrive.jp/android/xml_layout/index6.html にて、 > Activityクラスで定義されているfindViewByIdメソッドを使用します。 > 引数にリソースIDを指定すると、対応するビューのオブジェクトを返します。 > 実際に使用する時は戻り値をそのビューのクラスでキャストして下さい。 と書いてありました。 しかし「ビューのクラスでキャスト」と言われても、なぜそうするのか腑に落ちません。 そもそも「オブジェクト型をキャストする」という概念がなかなか理解できません。 これがたとえば「stringをintにキャストする」ならば直感的に意味が理解できます。 「文字列としての1を、計算できる数字の1に変換して扱うんだな」って直感的に理解できる。 でもオブジェクト型をキャスト・・・っていう概念が全くわかりません。 どう理解したら良いでしょうか?
kaputaros

2015/09/09 06:14 編集

オブジェクト型のキャストを理解するには、クラスの親子関係についてわかる必要があると思います。 ↓こちらのサイトなど、 javaの基本をまとめてくれているサイトはいろいろあるので 一度見てみるといいかもしれませんね。  Javaの道:クラス (http://www.javaroad.jp/java_class2.htm) --- あと、String型はint型にはキャストできません。 Javaには「オブジェクト型(参照型)」と「プリミティブ型(基本型)」というものがあります。 ↓こちらのサイトがわかりやすい・・・かな?  Javaのプリミティブ型と参照型について(http://promamo.com/?p=2818) ちなみにStringはオブジェクト型、intはプリミティブ型です。 オブジェクト型⇔プリミティブ型 に変換するには、"ラッパークラス"という プリミティブ型をオブジェクト型として扱うことができるクラスを使う必要があります。
zico_teratail

2015/09/10 15:52

>String型はint型にはキャストできません。 PHPで言うところのstringをintにキャスト・・・と同じつもりでいましたが、Javaではそれに該当するのはcharとintであり、Stringはオブジェクト型なんですね。 へっぽこPHPerの常識ではなかなか理解するのに苦労しました。というかまだ理解しきれていませんが、とにかくオブジェクト型とプリミティブ型という違いがあるのだということは分かりました。
guest

0

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

まず「宣言」から。
コピペでやったので意識が薄いと思いますが、

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);」という右辺になるのです。
これが、親子関係にないクラスであれば、必要なプロパティだけ手書きで設定しなければいけないという煩わしいことになります。

投稿2015/09/13 13:11

TetsujiMiwa

総合スコア1124

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

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

投稿2015/09/09 04:12

編集2015/09/09 04:15
pice

総合スコア409

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zico_teratail

2015/09/09 04:45

ありがとうございます。 リンク先を読み、キャストしているということは理解しました。 しかし、「オブジェクト型をキャストする」という概念がなかなか理解できません。 これがたとえば「stringをintにキャストする」ならば直感的に意味が理解できます。 「文字列としての1を、計算できる数字の1に変換して扱うんだな」って直感的に理解できる。 でもオブジェクト型をキャスト・・・っていう概念が全くわかりません。 どう理解したら良いでしょうか?
swordone

2015/09/09 06:18

Stringからintへは「キャスト」できません. それは文字を数値に「解析」してるのであって,キャストではありません. 数値を表すプリミティブ型同士(int⇔longなど)はキャストですが. オブジェクト型(参照型)のキャストを理解するためには,まずは「継承」について理解しないといけません.おそらく継承が何かわかっていないのではないでしょうか?
zico_teratail

2015/09/10 15:55

継承については一応わかっていたつもりですが、今回質問したコード中にあるようなキャストが必要になる場合における継承の影響は、yona様の回答でなんとなく理解できた気がします。 とにかくOOPに不慣れな者からすると、「オブジェクト型」という概念をナチュラル感覚で理解するのは非常に難しいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問