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

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

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

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

参照

参照は、プログラミングにおいて変数や関数といったメモリ空間上での所在を指示するデータのことを指します。その中にはデータ自体は含まれず、他の場所にある情報を間接的に指示するプログラムです。

Java

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

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

1906閲覧

String配列の文字列の要素charはメモリのどこにある?

FLD2047

総合スコア1

char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

参照

参照は、プログラミングにおいて変数や関数といったメモリ空間上での所在を指示するデータのことを指します。その中にはデータ自体は含まれず、他の場所にある情報を間接的に指示するプログラムです。

Java

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

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

2グッド

4クリップ

投稿2023/12/05 07:10

編集2023/12/06 07:50

わからないこと

最近諸事情でJavaの勉強を始めた者です(非情報系)、知識としては過去にC言語を講義でほんの少しだけ齧ったことのある程度です。

Javaにおける配列で疑問に思ったことがありますので質問させていただきます。

合っている自信がないのですが、内部的には下記のような状態になっていると現状は理解しています(間違っていたら指摘ください)

①配列を宣言した際、宣言した配列の変数には配列そのものではなくその配列の実体を示す参照値が格納され、その参照値はスタック領域に配置される。
②newでインスタンス生成した際に配列そのものがオブジェクトとしてヒープ領域に配置される。
③配列の要素の実体もヒープ領域にあり、配列の変数[番号] に定義(格納)された参照値を用いることで実体にアクセスすることができる。
④String型はクラスであり、こちらだけ特別に宣言の際に自動でヒープ領域にインスタンス(文字列リテラル)が生成され、宣言したString変数に参照値が格納される。
⑤String型の中身はchar型の文字要素で構成された配列オブジェクトであり、一つ一つの文字の実体はそれぞれヒープ領域に配置されている。

上記を踏まえまして、String型の配列を宣言した際の内部の状態が知りたいです。

例えば
String[] strings = {"あいうえお", "ABCDE", "一二三四五"};
で定義された配列があった場合、
stringsに格納されている参照先に"あいうえお"と"ABCDE"と"一二三四五"の3つの文字列リテラルの実体要素を持つオブジェクトがヒープ領域にあると今まで思っていました。

ですがString型文字列の中身がchar型の配列だということを考えると、String配列から見たchar型の文字要素は「配列の要素の中のさらに配列の要素」という位置付けになってしまいます。

この場合、ヒープ領域にあるString型配列の中の文字列要素を参照して、(文字列は配列なのでchar型の文字要素の参照値を持つと考えて)また更にどこかにあるchar型文字要素を参照する動きになるのでしょうか? もしそうならどこにそのような領域を確保しているのでしょうか? この場合のchar型文字は内部でどのような状態になっているのでしょうか?

上記のことをずっと考えては調べてを繰り返してしまい先に進めない状態です。
実はJavaの配列に入った際も配列宣言がなぜそのまま行えるのかが頭で納得できず何日か止まっていました(そして上の①〜③に辿り着きました)
今回も同じように止まってしまい参考書が終わらない予感がしたためこちらで質問させていただきました、本当なら「こういうものだ」と受け入れて先に進みたいのですが出来ない性分で、、、

拙い文章で申し訳ございませんが、お答えくださると嬉しいです。

2023/12/6追記
使用している参考書を進めていましたところ、先日まで自分が受け入れられず悩んでいた「参照」「文字列と文字配列」「C/C++との違い」に関する解説が書かれていました。
「とりあえず受け入れて先に進む」ことの大事さを身をもって痛感しました。

exnjinia, GenbuHase👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2023/12/05 10:36 編集

以下のプログラムの場合、Stringの中身はconstant poolにあります。 これはスタックでもヒープでもなく、メソッド領域と呼ばれる場所に配置されてます。 String[]はヒープに作成されます。 $ java --version openjdk 19.0.2 2023-01-17 OpenJDK Runtime Environment (build 19.0.2+7-Ubuntu-0ubuntu322.04) OpenJDK 64-Bit Server VM (build 19.0.2+7-Ubuntu-0ubuntu322.04, mixed mode, sharing) $ cat Question.java class Question { public static void main(String[] args) { String[] strings = {"あいうえお", "ABCDE", "一二三四五"}; for (var s: strings) { System.out.println(s); } } } $ javac Question.java $ javap -v Question Classfile /home/user/tmp/Question.class Last modified 2023/12/05; size 607 bytes SHA-256 checksum 553ffbb0243d236b17e2df2cadd69058a16ca08bf0d0bc5d01b43c44fc377daf Compiled from "Question.java" class Question minor version: 0 major version: 63 flags: (0x0020) ACC_SUPER this_class: #27 // Question super_class: #2 // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 1 Constant pool: #1 = Methodref #2.#3 // java/lang/Object."<init>":()V #2 = Class #4 // java/lang/Object #3 = NameAndType #5:#6 // "<init>":()V #4 = Utf8 java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Class #8 // java/lang/String #8 = Utf8 java/lang/String #9 = String #10 // あいうえお #10 = Utf8 あいうえお #11 = String #12 // ABCDE #12 = Utf8 ABCDE #13 = String #14 // 一二三四五 #14 = Utf8 一二三四五 #15 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream; #16 = Class #18 // java/lang/System #17 = NameAndType #19:#20 // out:Ljava/io/PrintStream; #18 = Utf8 java/lang/System #19 = Utf8 out #20 = Utf8 Ljava/io/PrintStream; #21 = Methodref #22.#23 // java/io/PrintStream.println:(Ljava/lang/String;)V #22 = Class #24 // java/io/PrintStream #23 = NameAndType #25:#26 // println:(Ljava/lang/String;)V #24 = Utf8 java/io/PrintStream #25 = Utf8 println #26 = Utf8 (Ljava/lang/String;)V #27 = Class #28 // Question #28 = Utf8 Question #29 = Utf8 Code #30 = Utf8 LineNumberTable #31 = Utf8 main #32 = Utf8 ([Ljava/lang/String;)V #33 = Utf8 StackMapTable #34 = Class #35 // "[Ljava/lang/String;" #35 = Utf8 [Ljava/lang/String; #36 = Utf8 SourceFile #37 = Utf8 Question.java { Question(); descriptor: ()V flags: (0x0000) Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=6, args_size=1 0: iconst_3 1: anewarray #7 // class java/lang/String 4: dup 5: iconst_0 6: ldc #9 // String あいうえお 8: aastore 9: dup 10: iconst_1 11: ldc #11 // String ABCDE 13: aastore 14: dup 15: iconst_2 16: ldc #13 // String 一二三四五 18: aastore 19: astore_1 20: aload_1 21: astore_2 22: aload_2 23: arraylength 24: istore_3 25: iconst_0 26: istore 4 28: iload 4 30: iload_3 31: if_icmpge 54 34: aload_2 35: iload 4 37: aaload 38: astore 5 40: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream; 43: aload 5 45: invokevirtual #21 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 48: iinc 4, 1 51: goto 28 54: return LineNumberTable: line 3: 0 line 4: 20 line 5: 40 line 4: 48 line 7: 54 StackMapTable: number_of_entries = 2 frame_type = 255 /* full_frame */ offset_delta = 28 locals = [ class "[Ljava/lang/String;", class "[Ljava/lang/String;", class "[Ljava/lang/String;", int, int ] stack = [] frame_type = 248 /* chop */ offset_delta = 25 } SourceFile: "Question.java" $ ご参考までに。
guest

回答2

0

本当なら「こういうものだ」と受け入れて先に進みたいのですが出来ない性分で

プログラミング言語の学習においては、むしろ意識的にそれをやらなければなりません。


仕様がしっかり決まっているプログラミング言語の場合、仕様実装を峻別して考える必要があります。ぶっちゃけていえば、「仕様書通りの動作をするのであれば実装の中身はどんなものでも構わない」、全く別な中身の実装があっても構わないぐらいのものです。

速度やメモリ消費量、未定義の動作で何が起きているのかなど、実装起因の問題に巻き込まれている、もしくは実装自身やプラグイン開発を始めるような状況であれば話は別ですが、そうでなければ「仕様にこう書いてあるからこう動作する」以上に考えても、プログラミング言語を利用する側としての実質的な利益はありません。

投稿2023/12/05 08:43

maisumakun

総合スコア145930

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

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

maisumakun

2023/12/05 08:44 編集

うっかり特定の実装がもたらす挙動に依存したコードを書いてしまった場合、実装の変化で動かなくなる事態が訪れかねませんので、意識的に「明文化された仕様だけを信じて」コードを書くほうが、より適切です。
FLD2047

2023/12/06 00:20

>> プログラミング言語の学習においては、むしろ意識的にそれをやらなければなりません。 >> 仕様がしっかり決まっているプログラミング言語の場合、仕様と実装を峻別して考える必要があります。 >> そうでなければ「仕様にこう書いてあるからこう動作する」以上に考えても、プログラミング言語を利用する側としての実質的な利益はありません。 ここの辺りは自分では全く思いつかなかったことであり、今まで読んだことのある本には書いてなく、他の人から聞いたこともなかったです。 おそらく多くの方は自然にそのような考えができているor習慣ついているのでしょう。 このような自分が長年たどり着けなかった価値観や考え方を知ることができて本当に質問して良かったです。 それ以外にも「こういう場合〜」などの例外も複数挙げてくださったのも助かりました。 貴重なご回答誠にありがとうございました。
guest

0

ベストアンサー

char 配列と String は別モノです。
String の要素である char はプリミティブ型ですので参照ではありません。

①配列を宣言した際、宣言した配列の変数には配列そのものではなくその配列の実体を示す参照値が格納され、その参照値はスタック領域に配置される。

配列の変数の ”宣言” 時は、まだ配列の実体はありませんので「配列の実体を示す参照値が格納され」てはいません。

②newでインスタンス生成した際に配列そのものがオブジェクトとしてヒープ領域に配置される。

"配列はオブジェクト"です。

③配列の要素の実体もヒープ領域にあり、配列の変数[番号] に定義(格納)された参照値を用いることで実体にアクセスすることができる。

配列の要素が"参照かどうか"は配列の型によって違います。 String 等のオブジェクトなら参照ですが、 char 等のプリミティブは実体です。

④String型はクラスであり、こちらだけ特別に宣言の際に自動でヒープ領域にインスタンス(文字列リテラル)が生成され、宣言したString変数に参照値が格納される。

String 型の変数も他の(配列を含む)オブジェクト変数と同様に "宣言" 時はまだ参照が入っていません。
変数どうこうでは無く、"文字列リテラル" 自体が特別に String として扱われるものです。

⑤String型の中身はchar型の文字要素で構成された配列オブジェクトであり、一つ一つの文字の実体はそれぞれヒープ領域に配置されている。

String が 配列的 に扱うメソッドを持っていたとしても、内部が char 配列で実装されていると決定することはできません。
java はオブジェクト指向であり、オブジェクトはカプセル化によって詳細を外部が意識しなくて済むようにしています。(かならずしも成功はしていませんが。)

オブジェクトや変数がスタックに出来るのかヒープに出来るのかはプログラム的にはスコープの問題だと思いますので、 java でのスコープさえ理解していれば、スタックかヒープかという問いは不要でしょう。

投稿2023/12/05 08:10

編集2023/12/05 08:38
jimbe

総合スコア13168

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

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

FLD2047

2023/12/05 08:35

文字配列と文字列は別モノなのですね、一緒くたにして考えてしまってました。 それでしたらString型配列は何も不自然なものではないと受け入れられるかもしれません。 他にも自分が間違って理解してることはどこか改めて調べてみます、ご回答ありがとうございました。
FLD2047

2023/12/06 00:30

私の質問を今見返したらメチャクチャなこと言ってましたね……細かく訂正してくださって本当にありがとうございます。 jimbe様のご回答をもとに改めて用語や概念など含め自分の理解をそれそれ訂正するようにいたします。 またオブジェクト指向そのものについてや、Javaの思想(何を目的にこのような仕様になっているか)も全く知らなかったのでこちらも併せて知っていきたいと思います。 学習においてはメモリ云々を考える暇があるならスコープを意識して進めていくようにいたします。 改めてご回答誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問