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

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

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

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

Q&A

解決済

5回答

7774閲覧

擬似プリミティブ型とは何なのか?

raccy

総合スコア21735

Java

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

2グッド

1クリップ

投稿2016/10/13 10:03

Javaには擬似プリミティブ型なるものがあると、今朝初めて知りました。どうやらStringにおける==equals()の違い(下記コードを参照)を説明するのに使われるようです。

Java

1String a = "abc"; 2String b = "abc"; 3String c = new String("abc"); 4System.out.println(a == b); // true 5System.out.println(a == c); // false 6System.out.println(a.equals(b)); // true 7System.out.println(a.equals(c)); // true

調べるといくつかのサイトで上の動作の説明として擬似プリミティブ型という用語を使っています。

fc2 blogの多さも気になるところですが、コレは単に「文字列リテラル(及び定数式)は以前作られたオブジェクトと同じであれば再利用されて同じオブジェクトになる」ということだけで説明が足りるのではないかと思っています。

参考: Java言語規定 字句文法#3.10.5 文字列リテラル

それに、擬似プリミティブを宣言するとか言っている記事もあり、普通のStringを代入はできない型になってしまうとでも言うのでしょうか。さらには参照値ではなく、文字列が直接変数に入れられるという説明をしているところまであります(JavaScriptの話ではないはずなんですが…)。言語仕様として擬似プリミティブ型なる用語が使われている所も見つけられませんでしたし、公式の用語なのかもよくわかりません。

そこで質問です。

擬似プリミティブ型はJavaの用語の一つであり、この擬似プリミティブ型を使った==の説明は妥当であると言えるのでしょうか?

ここでの妥当であるとは、teratailの回答として採用すべきかどうかと言うことです。もし、妥当であるというのであれば、擬似プリミティブ型の定義とは何なのか?何が他と異なるのか?同じように再利用される場合があるオートボクシングされたプリミティブ型のラッパークラスも同じように擬似プリミティブ型と言うのか?リテラル(及び定数式)はオブジェクトが再利用されるという説明ではどのような不備がある、または、その説明よりも優れているというのか?そういった点を教えて欲しいです。また、Oracles(旧Sun)の公式資料があるというのであれば、ぜひ紹介してください。

あと、似なのか似なのかも気になる所なので、どっちが良いかもあわせて答えてくれたら嬉しいです。

参考質問
Java - String型の比較について
Java - [==]と[equals]の挙動の違いを確認したい。

mpyw, yohhoy👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2016/10/13 10:40

コンスタントプールやStringプールはご存知ですか?String.intern()の機能は?Syste.identityHashCode()で参照値を見たことがありますか?これらを知っている人は疑似という言葉は使いませんでした。
raccy

2016/10/13 11:45

Javaの仕様はそれなりに知っているつもりでしたが、全く知らない「擬似プリミティブ型」という用語に出くわしたためにこのような質問をさせていただきました。そもそもそんな用語は無い、そんな言葉を使っているサイトは間違っているというのであれば、その内容を回答に書いていただければと思います。
guest

回答5

0

ベストアンサー

私の結論から言うと、「疑似プリミティブ」という言葉は妥当ではないと考えます。

「疑似プリミティブ」という言葉を使っているサイトをいくつか読みましたが、どうも

  • 「int型変数に10という字で書いた値(つまりリテラル)をnewなどせず代入できるのと同じように、String型の変数もnewせずにリテラルで代入できる」という特徴
  • そのようにして代入した変数が「"=="で同じと判定される」という文字列プールの仕組みから生じた現象

を取り上げて、「まるでプリミティブのような動作じゃないか」ということで「疑似プリミティブ」という言葉を使っているように読み取れます。
逆に言うと、ただそれだけなんですよね。プリミティブ型のような特性を持っているのが文字列リテラルに限った話であり、それとStringオブジェクトを分離して考え出すと後々の混乱につながりかねません。具体的には「この変数って疑似プリミティブとして入れたっけ?」と考え出すとキリがなくなります。疑似プリミティブとして入れたとしても文字列連結が何処かで起こればその前提が崩壊します。

また、ラッパークラスのオートボクシングはラッパークラスのvalueOfメソッドを使用しており、このメソッドでプールされる値は範囲が限定されています。範囲外の値を扱おうとしたときに、プリミティブとして入れたはずなのに"=="での比較がおかしい、などという事態にもなりえます。

なので、ここで挙げている「疑似プリミティブ」なるものの根拠は従来通り「文字列リテラルの特徴」として扱い、疑似プリミティブという言葉は使わないほうが妥当でしょう。

ちなみに「疑似」「擬似」については→「擬似」と「疑似」の違いはありますか?

投稿2016/10/13 12:50

swordone

総合スコア20651

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

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

raccy

2016/10/13 15:52

まるでプリミティブみたいだから擬似プリミティブ…たしかにそんな発想をしていそうですね、安易すぎるとしか思えませんが。私も逆に混乱するのでは思っています。記事を書いている人達は本当にわかりやすいと思っているのか、不思議に思っているところです。
swordone

2016/10/13 15:55

というか、これを使っている記事がどうも「リテラル」と「プリミティブ」を混同している気がしてならないんですよね。
mpyw

2016/10/13 16:41 編集

Googleで範囲指定検索して見つかる限りでは,javayuriさんのブログが初出みたいです.「リテラルとプリミティブを混同している」というのは的確な指摘だと思います.不適当な初心者の解釈が拡散されてしまった結果でしょうかね… → と思ったら2007年のさらに古いやつ (hrastamanさん) もありましたね,失礼しました 「文字列は頻繁に使うために、プリミティブ型と同様の操作性を確保するために採用された特例措置によるものです。」 最適化の一環に過ぎなかったと思うので,ちょっとこの主張はいかがなものかと…
swordone

2016/10/14 05:20

JavaのStringクラスのドキュメントにも、文字列リテラルはnew String(char配列)と同じだと書いてますしね… もっとも、文字列プールの話があるので、実際はさらにinternメソッドで囲ったような形になるのでしょうが。
swordone

2016/10/21 02:10

あ、Stringがswitch文で使えるようになったからよりプリミティブに近くなったという見方はできるかも… ただenumでもできるからなあ…
guest

0

Javaの文脈で「疑似プリミティブ型」という単語は初耳でした。少なくとも厳密なJava言語仕様としては、そのような分類の型は存在しないはずです。

英語圏で対応する(と思われる)"pseudo primitive type" で検索してみたところ、数は少ないもののいくつか使用例があるようです。いくつか眺めた傾向としてはString型や文字列リテラルがコンパイラに特別扱いされること、オートボクシングを伴うIntegerDoubleなどのプリミティブ型ラッパークラスを指すケース、int[]のような配列型(何故??)を指すレアケースがあるようです。

個人的には「疑似プリミティブ型」が広く普及した名称とは思えませんし、説明において無用にオレオレ概念を導入すべきではないと考えます。


ここから先は意地悪な(ひねくれた)解釈です。典型的な「String型は疑似プリミティブ型」論法は、下記のような説明でしょう。

Java

1SomeClass a = new SomeClass(引数); // 普通のクラス(参照型)はこう書くよね 2 3String s1 = new String("ABC"); // '疑似'プリミティブ型はこうも書けるけど... 4String s0 = "ABC"; // 文字列リテラルを直接代入もできるよ! 5 6int v = 42; // プリミティブ型と同じようにね

この説明では「new String("ABC")に渡している引数"ABC"の型は何なのか?」というギモンが生まれ、「引数をとるコンストラクタでは各引数の型宣言を行う」仕様との整合性の観点で破綻しています。もちろん「疑似プリミティブ型は特別なのだ」や「ソースコード上の"ABC"という表記は第三の謎型を持ち、String型はそれを受け取って初期化できるのだ」というこじつけ説明は可能ですが、そのような謎かけ説明をするくらいなら「String型もまた参照型である/文字列は良く使う機能なので特別扱いされる」というシンプルな説明が好ましいと考えます。

また、String型の振る舞いは本質的に参照型であるにもかかわらず、疑似プリミティブ型という語によりプリミティブ型の一種と誤解されるリスクが高い点もマイナス要素と考えます。

Keep it simple, stupid!

投稿2016/10/14 00:50

編集2016/10/14 01:44
yohhoy

総合スコア6191

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

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

raccy

2016/10/14 09:49

一応英語圏でも少ないながらあるにはあるのですか…ただやはりレアっぽいですね。私も「擬似プリミティブ型」という概念(?)の説明が逆に混乱する要因になるのではと思っています。私自身が混乱しましたので。
guest

0

文字列リテラルの事を指して擬似プリミティブと言っているのではないでしょうか。
私も聞いた事ありませんでした。仕様書にもそれらしいのは見たことありませんね。

また、==とequalsの説明には必要ないと思います。

投稿2016/10/13 12:14

編集2016/10/13 12:15
yona

総合スコア18155

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

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

raccy

2016/10/13 15:32

そうそう、私も初めて聞いたものだから、こんな質問をしたのです。この用語が知っていて当たり前と言われたら、自称Java歴10年以上の自信が脆くも崩れ落ちているところでした(まぁ、Javaをメインで使っているわけじゃ無いですから、そこそこなものしか書けないんですけどね)。
guest

0

文字列リテラルのことですね。土曜日に、文字列リテラルがJVMでどのように扱われるのか実験してみます。
検索キーワードをあげておきます。

  • Flyweightデザインパターン
  • コンスタントプール
  • Stringプール
  • String.intern()

###回答(追記)
『擬似プリミティヴ型』は『Java言語仕様』にも『Java仮想マシン仕様』にも定義されていません。私はこの言葉に何の意味も見出せません。質問に回答すべきではなかったと思いますが、擬似的な解説のようなものを書いてみます。

「擬似プリミティブ型」なるものがどのようなものかを知りたいのです。

これはご自分で結論を書かれています。Du sagt.

「擬似プリミティブ型」の定義、文字列リテラルとはどのような関係なのか、そういった点です。

文字列リテラルと全く同じではない。他の回答者のswordoneさんが触れている『文字列プール』に格納された文字列(あるいは文字列の参照)だと解釈することができます。別の言い方をすると”intern”された文字列です。「文字列リテラルとは定数式のことで、唯一のインスタンスを共有するよう”intern”されたものである。」(下手な翻訳) 

###String.intern(追記)
以下は蛇足ですが、実験コードを書きます。
文字列リテラルを先に『文字列プール」に格納して後から、同じ文字列のインスタンスをヒープに作成してinternする。

Java

1String a = "abcd"; 2System.out.println(System.identityHashCode(a)); 3 4String b = new String(new char[]{'a','b','c','d'}); 5System.out.println(System.identityHashCode(b)); 6 7b = b.intern(); 8System.out.println(System.identityHashCode(b));

バイトコードは、aに文字列リテラルを代入するのは putfield、bに代入する文字列をnewするのはinvokespecial、internするのはinvokevirtualです。

文字列リテラルより先に、文字列をヒープにインスタンス化してinternしてみる。

Java

1String c = new String(new char[]{'e','f','g','h'}); 2System.out.println(System.identityHashCode(c)); 3 4c = c.intern(); 5System.out.println(System.identityHashCode(c)); 6 7String d = "efgh"; 8System.out.println(System.identityHashCode(d));

先に登録したものが使われることがわかります。
最後に、言うまでもないことですが、文字列プールに格納された文字列は、次のことが成り立ちます。

a == b ならば a.equals(b) // 言語仕様のとおり
a.equals(b) ならば a == b // Flyweight型の文字列

ラッパークラスのvalueOfが事前に用意されたインスタンスを返すことについては省略します。
なぜ言語仕様にString.internが書かれなければならなかったのか、こちらの方が気になります。

投稿2016/10/13 20:52

編集2016/10/14 12:28
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

raccy

2016/10/13 21:38

いえいえ、文字列リテラルにどのような性質があるかと言うことを知りたいわけではありません(それは質問で参考文献に上げたJava言語規定を読めばわかりますので)。「擬似プリミティブ型」なるものがどのようなものかを知りたいのです。「擬似プリミティブ型」の定義、文字列リテラルとはどのような関係なのか、そういった点です。
raccy

2016/10/14 13:11

結局、vornan19さんの結論は何になるのでしょうか?「擬似プリミティブ型なんてものは無い」ということであれば、それだけで十分なのですが…。
退会済みユーザー

退会済みユーザー

2016/10/14 13:53

未定義語、悪く言えばバズワードです。
raccy

2016/10/14 14:20

なるほど、未定義と言うことは、説明するための用語としては用いるべきでは無いと言うことですね。
guest

0

http://hrastaman.blog92.fc2.com/blog-entry-6.html
のサイトに擬似プリミティブ化とインスタンス化に関する例が
出ています。

正式用語でないかもしれませんが、一部で使われているようですね。

ご参考まで

投稿2016/10/14 15:56

Yatsurugi

総合スコア1628

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

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

swordone

2016/10/14 16:12

それ質問に掲載しているURLの一つじゃないですか…
raccy

2016/10/14 19:48

質問であげているサイトの一つではありますが、Yatsurugiさんはそのサイトの説明が正しく、わかりやすく、理にかなっているとお考えなのでしょうか?しかし、わたしはそれらのサイトを読んでも、いまいち要領を得られませんでした。ぜひ、Yatsurugiさんの言葉で「擬似プリミティブ型」がなんなのか説明いただけませんか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問