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

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

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

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

Java

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

Q&A

2回答

739閲覧

ジェネリクスを用いたコンストラクタ呼び出しで、Integer型の値がString型に代入?できてしまう。

Ryuu6490

総合スコア9

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

Java

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

0グッド

0クリップ

投稿2023/03/04 12:44

実現したいこと(想定される結果)

[Integer型をStringに変換できません]
等のコンパイルエラーが発生する。

前提

1.該当のソースコードを、下記のコマンドでコンパイル。
javac -encoding UTF-8 Test.java
2.続けて、下記のコマンドで実行。
java Test
3.以下の出力結果となる。
1

発生している問題・エラーメッセージ

・エラーメッセージ無し。
・12行目で new Generic<Integer>(1) と、Integer型の値1を
3行目のコンストラクタに渡しています。
定義側の引数はString型なので、Integer型と String型の相互変換はできないはずですが、
なぜできるのでしょうか?

該当のソースコード

Test.java

1class Generic<String> { 2 String str; 3 public Generic(String str) { 4 this.str = str; 5 } 6 public String getString() { 7 return str; 8 } 9} 10public class Test { 11 public static void main(String[] args) { 12 Generic<Integer> g = new Generic<Integer>(1); 13 System.out.println(g.getString()); // 1 を出力 14 } 15}

試したこと

・数値(int)と文字列(String)の変換方法について調べました。Integer型をString型に変換する方法として、IntegerクラスのtoStringメソッドがありますが、特別呼び出していないので、関係なさそうです。
※現在調査中につき、また何か気づいたら、追記します。
参考サイト
https://style.potepan.com/articles/18052.html

補足情報(FW/ツールのバージョンなど)

Windows10,
openjdk version "11"
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
Visual Studio Code
ここにより詳細な情報を記載してください。

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

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

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

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

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

dameo

2023/03/04 13:29

型パラメータをStringにしてるからですよ。一行目は class Generic<T> { みたいに書くのが普通です。このため一見Stringに見える部分は型パラメータとして扱われています。 型パラメータではなく、java.lang.Stringと記述すればこの問題は解決します。 例えばコードとしては、6行目を public java.lang.String getString() { とかすれば目出度く怒られる気がします(手元にはopenjdk14しかないので他でどうなるか知らない)。
jimbe

2023/03/04 15:27

この問題に Windows10 や VisuanStudioCode は関係するのでしょうか。(これら以外では発生しないとか。) 関係しなければ、これらのタグは不要です。
xebme

2023/03/05 22:40 編集

<>の中には識別子が書けます。 識別子はキーワードを除く、a-zA-Z$0-9_のうち数字で始まらない文字列 <String>のStringは識別子です。そしてただの変数名にすぎません。 例えば、左のStringは型、右のStringは変数名になります。 record Gen(String String) {}
guest

回答2

0

変数

変数は、実行時に値が決まる、あるいは値を変更することができる、メモリの場所です。
変数には、識別子として許される任意の名前をつけることができます。たとえば、String型の変数にStringという名前を付けられます。

Java

1 String String; // Stringという名前の変数の定義 2 String = "5"; // 変数に値を代入 3 System.out.println(String);

変数名Stringは、使われていない別の名前に一括置換してもプログラムの機能は変わりません。

Java

1 String x; 2 x = "5"; 3 System.out.println(x);

型変数とは

型変数は、コンパイル時に型が決まる変数です。型はObjectの派生型になります。
型変数には使用時に型を代入できますが、代入の仕方が変数とは異なります。

Java

1 record Generic<String>(String x){} // Stringという名前の型変数の定義 2 // 以下は、インスタンスを生成する際に、型変数Stringに具体的なクラス(型)を代入していると考えられる 3 Generic<Integer> g1 = new Generic<>(5); 4 Generic<String> g2 = new Generic<>("5"); 5 Generic<Character> g3 = new Generic<>('5');

型変数も、使われていない別の名前に一括置換できます。Tには任意の型を指定できる。

Java

1record Generic<T>(T x){} // 型変数Tの定義 2Generic<Integer> g1 = new Generic<>(5); 3Generic<String> g2 = new Generic<>("5"); 4Generic<Character> g3 = new Generic<>('5');

クラス名と同じ型変数を使う弊害

型変数にStringという名前をつけると、そのクラスの中でString型の変数が定義できなくなります。Stringは型変数の名前に使ってしまったので、型Stringが型変数名Stringで隠されてしまった。コンパイル時に警告が出ます。

インスタンスを生成するときに、xに任意の型を指定したい。yはString型固定で使いたい、としたら。

Java

1 @SuppressWarnings("hiding") 2 record Generic1<String>(String x, String y){} // x,yは任意の型 3 Generic1<Integer> g4 = new Generic1<>(1,2); // x,yはInteger型 4 5 @SuppressWarnings("hiding") 6 record Generic2<String>(String x, java.lang.String y){} // xは任意の型、yはString型 固定 7 Generic2<Integer> g5 = new Generic2<>(1,"abcd"); // xはInteger型、yはString型 固定

本来のString型を使いたい時は、仕方なく、完全修飾名java.lang.Stringを指定しています。

投稿2023/03/07 12:18

xebme

総合スコア1081

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

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

xebme

2023/03/07 12:24

次のように質問のタイトルを訂正してください 誤:Integer型の値がString型に代入?できてしまう。 正:Integer型がString型変数に代入できてしまう。
guest

0

定義側の引数はString型なので、

いわゆる java.lang.String 型ではありません。 "String" はジェネリクスの型として指定されている文字列の為、任意の型を表します。

ジェネリクスは、 <> の中に書いた文字列が型として書いてある部分を、使用時の <> の型に置換したように動作します。

java

1class Generic<String> { 2 String str; 3 public Generic(String str) { 4 this.str = str; 5 } 6 public String getString() { 7 return str; 8 } 9}


・フィールド str の型
・コンストラクタのパラメータ str の型
・getString() メソッドの型
に "String" という文字列が指定されているため、g = new Generic<Integer>(1);とした時の g は

java

1class Generic { 2 Integer str; 3 public Generic(Integer str) { 4 this.str = str; 5 } 6 public Integer getString() { 7 return str; 8 } 9}

と同じようなクラスのオブジェクトとなります。
コンストラクタで指定した 1 はオートボクシングで Integer に変換後 str フィールドに保存され getString() で返されるだけで、変数名・メソッド名が 人間にとって紛らわしいですがコードとしては何の問題もありませんので、エラーにはなりません。
System.out.println はオブジェクトの toString() を呼び出すので 1 が表示されるでしょう。

投稿2023/03/04 15:34

編集2023/03/06 05:40
jimbe

総合スコア12545

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問