目次
1. String 文字列のメモリ割り当てから始めましょう
読者の多くはこの方法についてあまり知らないかもしれませんが、重要ではないというわけではありません。まず intern() メソッドのソース コードを見てみましょう:
1.一个关于intern()的简单例子
2.改造例子,再看intern
2).JDK6的运行结果分析
三、String类的结构及特性分析
1.不同JDK版本之间String的差异
2.String字符串的裁剪、拼接等操作分析
(1)String的substring实现
(2)String的字符串拼接实现
1)字符串拼接方案性能对比
2)三种字符串拼接方案原理分析
四、总结
ホームページ Java &#&ベース 過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

Sep 18, 2020 pm 05:32 PM
java

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

関連する学習に関する推奨事項: Java 基本チュートリアル

初心者向けJava では、Java が 2 つの主要なデータ型、つまり基本データ型と参照データ型に分類できることはすでに知られています。これら 2 つのデータ型のうち、String という特殊なデータ型があり、String は参照データ型ですが、他の参照データ型とは異なります。データ型の中でも奇抜な花と言えるでしょう。したがって、この記事では、Java の String 文字列について詳しく理解します。

1. String 文字列のメモリ割り当てから始めましょう

前回の記事「過去を振り返り、新しいことを学ぶ -- あなたの知らない JVM メモリ割り当て」では、JVM メモリ モデルを分析しました。詳細に。定数プールのセクションでは、文字列定数プール、クラス ファイル定数プール、実行時定数プールの 3 種類の定数プールについて学びました。文字列のメモリ割り当ては、文字列定数プールと大きな関係があります。

文字列のインスタンス化には 2 つの方法があることがわかっています。1 つ目の最も一般的に使用される方法は、リテラル代入によるもので、もう 1 つはパラメータを渡す構築方法によるものです。コードは次のとおりです:

    String str1="abc";
    String str2=new String("abc");复制代码
ログイン後にコピー

メモリ割り当てにおけるこれら 2 つの方法の違いは何ですか? 私たちが初めて Java を学習したときに、先生が説明してくれたと思います:

1。リテラル割り当てによる文字列の作成を渡すと、文字列定数プールに String オブジェクトのみが生成されます。 2. コンストラクターを介して String パラメーターを渡すと、ヒープ メモリと文字列定数プールに String オブジェクトが生成され、ヒープ メモリ内の String への参照がスタックに置かれます。

#この答えは正しいですか?それは使用される Java バージョンに完全に依存するため、少なくとも現時点では完全に正しいとは言えないようです。前回の記事「過去を振り返り、新しいことを学ぶ - あなたの知らない JVM メモリ割り当て」では、HotSpot 仮想マシンのさまざまな JDK での文字列定数プールの実装について説明しました。 ## JDK7以前は文字列定数プールはメソッド領域(永続生成)にあり、このときは文字列オブジェクトが格納されていました。 JDK7では、文字列定数プールはメソッド領域からヒープメモリに移動され、文字列オブジェクトはJavaヒープに格納されますが、文字列定数プールには文字列オブジェクトへの参照のみが格納されます。

この文をどのように理解すればよいでしょうか? String str1=new String("abc") を分析する例として取り上げます:

1. JDK6 のメモリ割り当て

図に示すように、まず JDK6 のメモリ割り当てを分析しましょう。以下:

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解するnew String("abc") が呼び出されると、Java ヒープと定数プールに "abc" オブジェクトが生成されます。同時に、str1 がヒープ内の「abc」オブジェクトを指すようにします。
2.JDK7 でのメモリ割り当て

JDK7 以降のバージョンでは、文字列定数プールがヒープ メモリに移動されるため、次の図に示すようにメモリ割り当て方法も異なります。 :

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解するnew String("abc") が呼び出されると、ヒープ メモリに 2 つの "abc" オブジェクトが作成され、str1 は「abc」オブジェクトと「abc」オブジェクトへの参照が定数プール内に生成され、別の「abc」オブジェクトを指します。
Java がこのように設計されている理由については、前の記事ですでに説明しています。
String は Java で最も頻繁に使用されるデータ型であるため、プログラムのメモリを節約し、プログラムのパフォーマンスを向上させるためです。 , Java の設計者は、すべてのクラスで共有される文字列定数プール領域を公開しており、各仮想マシンには文字列定数プールが 1 つだけあります。したがって、リテラル割り当てを使用する場合、文字列が文字列定数プールにすでに存在する場合、オブジェクトはヒープ メモリに再作成されず、文字列定数プール内のオブジェクトを直接ポイントします。

2. String の intern() メソッドString のメモリ割り当てを理解した後、String の非常に重要なメソッド String.intern() を理解する必要があります。

読者の多くはこの方法についてあまり知らないかもしれませんが、重要ではないというわけではありません。まず intern() メソッドのソース コードを見てみましょう:

/**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
    public native String intern();复制代码
ログイン後にコピー

emmmmm.... これは実際にはネイティブ メソッドですが、問題はありません。たとえソースが見えなくても

intern メソッドを呼び出すとき、文字列定数プールに String オブジェクトと等しい文字列が既に含まれている場合は、文字列定数プール内の文字列への参照が直接返されます。それ以外の場合、この文字列オブジェクトに含まれる文字列が定数プールに追加され、このオブジェクトへの参照が返されます。

1.一个关于intern()的简单例子

了解了intern方法的用途之后,来看一个简单的列子:

public class Test {    public static void main(String[] args) {
        String str1 = "hello world";
        String str2 = new String("hello world");
        String str3=str2.intern();
        System.out.println("str1 == str2:"+(str1 == str2));
        System.out.println("str1 == str3:"+(str1 == str3));
    }
}复制代码
ログイン後にコピー

上面的一段代码会输出什么?编译运行之后如下:

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

如果理解了intern方法就很容易解释这个结果了,从上面截图中可以看到,我们的运行环境是JDK8。

String str1 = "hello world"; 这行代码会首先在Java堆中创建一个对象,并将该对象的引用放入字符串常量池中,str1指向常量池中的引用。

String str2 = new String("hello world");这行代码会通过new来实例化一个String对象,并将该对象的引用赋值给str2,然后检测字符串常量池中是否已经有了与“hello world”相等的对象,如果没有,则会在堆内存中再生成一个值为"hello world"的对象,并将其引用放入到字符串常量池中,否则,不会再去创建。这里,第一行代码其实已经在字符串常量池中保存了“hello world”字符串对象的引用,因此,第二行代码就不会再次向常量池中添加“hello world"的引用。

String str3=str2.intern(); 这行代码会首先去检测字符串常量池中是否已经包含了”hello world"的String对象,如果有则直接返回其引用。而在这里,str2.intern()其实刚好返回了第一行代码中生成的“hello world"对象。

因此【System.out.println("str1 == str3:"+(str1 == str3));】这行代码会输出true.

如果切到JDK6,其打印结果与上一致,至于原因读者可以自行分析。

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

2.改造例子,再看intern

上一节中我们通过一个例子认识了intern()方法的作用,接下来,我们对上述例子做一些修改:

public class Test {
    public static void main(String[] args) {
        String str1=new String("he")+new String("llo");
        String str2=str1.intern();
        String str3="hello";
        System.out.println("str1 == str2:"+(str1 == str2));
        System.out.println("str2 == str3:"+(str2 == str3)); 
    }
}复制代码
ログイン後にコピー

先别急着看下方答案,思考一下在JDK7(或JDK7之后)及JDK6上会输出什么结果?

1).JDK8的运行结果分析

我们先来看下我们先来看下JDK8的运行结果:

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

通过运行程序发现输出的两个结果都是true,这是为什么呢?我们通过一个图来分析:

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

String str1=new String("he")+new String("llo"); 这行代码中new String("he")和new String("llo")会在堆上生成四个对象,因为与本例无关,所以图上没有画出,new String("he")+new String("llo")通过”+“号拼接后最终会生成一个"hello"对象并赋值给str1。

String str2=str1.intern(); 这行代码会首先检测字符串常量池,发现此时还没有存在与”hello"相等的字符串对象的引用,而在检测堆内存时发现堆中已经有了“hello"对象,遂将堆中的”hello"对象的应用放入字符串常量池中。

String str3="hello"; 这行代码发现字符串常量池中已经存在了“hello"对象的引用,因此将str3指向了字符串常量池中的引用。

此时,我们发现str1、str2、str3指向了堆中的同一个”hello"对象,因此,就有了上边两个均为true的输出结果。

2).JDK6的运行结果分析

我们将运行环境切换到JDK6,来看下其输出结果:

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

有点意思!相同的代码在不同的JDK版本上输出结果竟然不相等。这是怎么回事呢?我们还通过一张图来分析:

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

String str1=new String("he")+new String("llo"); 这行代码会通过new String("he")和new String("llo")会分别在Java堆与字符串常量池中各生成两个String对象,由于与本例无关,所以并没有在图中画出。而new String("he")+new String("llo")通过“+”号拼接后最终会在Java堆上生成一个"hello"对象,并将其赋值给了str1。

String str2=str1.intern(); 这行代码检测到字符串常量池中还没有“hello"对象,因此将堆中的”hello“对象复制到了字符串常量池,并将其赋值给str2。

String str3="hello"; 这行代码检测到字符串常量池中已经有了”hello“对象,因此直接将str3指向了字符串常量池中的”hello“对象。 此时str1指向的是Java堆中的”hello“对象,而str2和str3均指向了字符串常量池中的对象。因此,有了上面的输出结果。

通过这两个例子,相信大家因该对String的intern()方法有了较深的认识。那么intern()方法具体在开发中有什么用呢?推荐大家可以看下美团技术团队的一篇文章《深入解析String#intern》中举的两个例子。限于篇幅,本文不再举例分析。

三、String类的结构及特性分析

前两节我们认识了String的内存分配以及它的intern()方法,这两节内容其实都是对String内存的分析。到目前为止,我们还并未认识String类的结构以及它的一些特性。那么本节内容我们就此来分析。先通过一段代码来大致了解一下String类的结构(代码取自jdk8):

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {        /** The value is used for character storage. */
        private final char value[];        /** Cache the hash code for the string */
         private int hash; // Default to 0
        //  ...}复制代码
ログイン後にコピー

可以看到String类实现了Serializable接口、Comparable接口以及CharSequence接口,意味着它可以被序列化,同时方便我们排序。另外,String类还被声明为了final类型,这意味着String类是不能被继承的。而在其内部维护了一个char数组,说明String是通过char数组来实现的,同时我们注意到这个char数组也被声明为了final,这也是我们常说的String是不可变的原因。

1.不同JDK版本之间String的差异

Java的设计团队一直在对String类进行优化,这就导致了不同jdk版本上String类的实现有些许差异,只是我们使用上并无感知。下图列出了jdk6-jdk9中String源码的一些变化。

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

可以看到在Java6之前String中维护了一个char 数组、一个偏移量 offset、一个字符数量 count以及一个哈希值 hash。 String对象是通过 offset 和 count 两个属性来定位 char[] 数组,获取字符串。这么做可以高效、快速地共享数组对象,同时节省内存空间,但这种方式很有可能会导致内存泄漏。

在Java7和Java8的版本中移除了 offset 和 count 两个变量了。这样的好处是String对象占用的内存稍微少了些,同时 String.substring 方法也不再共享 char[],从而解决了使用该方法可能导致的内存泄漏问题。

从Java9开始,String中的char数组被byte[]数组所替代。我们知道一个char类型占用两个字节,而byte占用一个字节。因此在存储单字节的String时,使用char数组会比byte数组少一个字节,但本质上并无任何差别。 另外,注意到在Java9的版本中多了一个coder,它是编码格式的标识,在计算字符串长度或者调用 indexOf() 函数时,需要根据这个字段,判断如何计算字符串长度。coder 属性默认有 0 和 1 两个值, 0 代表Latin-1(单字节编码),1 代表 UTF-16 编码。如果 String判断字符串只包含了 Latin-1,则 coder 属性值为 0 ,反之则为 1。

2.String字符串的裁剪、拼接等操作分析

在本节内容的开头我们已经知道了字符串的不可变性。那么为什么我们还可以使用String的substring方法进行裁剪,甚至可以直接使用”+“连接符进行字符串的拼接呢?

(1)String的substring实现

关于substring的实现,其实我们直接深入String的源码查看即可,源码如下:

    public String substring(int beginIndex) {            if (beginIndex < 0) {                throw new StringIndexOutOfBoundsException(beginIndex);
            }            int subLen = value.length - beginIndex;            if (subLen < 0) {                throw new StringIndexOutOfBoundsException(subLen);
            }            return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
        }复制代码
ログイン後にコピー

从这段代码中可以看出,其实字符串的裁剪是通过实例化了一个新的String对象来实现的。所以,如果在项目中存在大量的字符串裁剪的代码应尽量避免使用String,而是使用性能更好的StringBuilder或StringBuffer来处理。

(2)String的字符串拼接实现

1)字符串拼接方案性能对比

关于字符串的拼接有很多实现方法,在这里我们举三个例子来进行一个性能对比,分别如下:

使用”+“操作符拼接字符串

    public class Test {        private static final int COUNT=50000;        public static void main(String[] args) {
            String str="";            for(int i=0;i<COUNT;i++) {
                str=str+"abc";
            }
    }复制代码
ログイン後にコピー
ログイン後にコピー

使用String的concat()方法拼接

    public class Test {        private static final int COUNT=50000;        public static void main(String[] args) {
            String str="";            for(int i=0;i<COUNT;i++) {
                str=str+"abc";
            }
    }复制代码
ログイン後にコピー
ログイン後にコピー

使用StringBuilder的append方法拼接

    public class Test {        private static final int COUNT=50000;        public static void main(String[] args) {
            StringBuilder str=new StringBuilder();            for(int i=0;i<COUNT;i++) {
                str.append("abc");
            }
    }复制代码
ログイン後にコピー

如上代码,通过三种方法分别进行了50000次字符串拼接,每种方法分别运行了20次。统计耗时,得到以下表格:

拼接方法最小用时(ms)最大用时(ms)平均用时(ms)
"+"操作符486851464924
String的concat方法222724562296
StringBuilder的append方法4126.6

从以上数据中可以很直观的看到”+“操作符的性能是最差的,平均用时达到了4924ms。其次是String的concat方法,平均用时也在2296ms。而表现最为优秀的是StringBuilder的append方法,它的平均用时竟然只有6.6ms。这也是为什么在开发中不建议使用”+“操作符进行字符串拼接的原因。

2)三种字符串拼接方案原理分析

”+“操作符的实现原理由于”+“操作符是由JVM来完成的,我么无法直接看到代码实现。不过Java为我们提供了一个javap的工具,可以帮助我们将Class文件进行一个反汇编,通过汇编指令,大致可以看出”+“操作符的实现原理。

    public class Test {        private static final int COUNT=50000;        public static void main(String[] args) {            for(int i=0;i<COUNT;i++) {
                str=str+"abc";
            }
    }复制代码
ログイン後にコピー

把上边这段代码编译后,执行javap,得到如下结果:

過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解する

注意图中的”11:“行指令处实例化了一个StringBuilder,在"19:"行处调用了StringBuilder的append方法,并在第”27:"行处调用了String的toString()方法。可见,JVM在进行”+“字符串拼接时也是用了StringBuilder来实现的,但为什么与直接使用StringBuilder的差距那么大呢?其实,只要我们将上边代码转换成虚拟机优化后的代码一看便知:

    public class Test {        private static final int COUNT=50000;        public static void main(String[] args) {
            String str="";            for(int i=0;i<COUNT;i++) {
                str=new StringBuilder(str).append("abc").toString();
            }
    }复制代码
ログイン後にコピー

可见,优化后的代码虽然也是用的StringBuilder,但是StringBuilder却是在循环中实例化的,这就意味着循环了50000次,创建了50000个StringBuilder对象,并且调用了50000次toString()方法。怪不得用了这么长时间!!!

String的concat方法的实现原理关于concat方法可以直接到String内部查看其源码,如下:

public String concat(String str) {        int otherLen = str.length();        if (otherLen == 0) {            return this;
        }        int len = value.length;        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);        return new String(buf, true);
    }复制代码
ログイン後にコピー

可以看到,在concat方法中使用Arrays的copyOf进行了一次数组拷贝,接下来又通过getChars方法再次进行了数组拷贝,最后通过new实例化了String对象并返回。这也意味着每调用一次concat都会生成一个String对象,但相比”+“操作符却省去了toString方法。因此,其性能要比”+“操作符好上不少。

至于StringBuilder其实也没必要再去分析了,毕竟”+“操作符也是基于StringBuilder实现的,只不过拼接过程中”+“操作符创建了大量的对象。而StringBuilder拼接时仅仅创建了一个StringBuilder对象。

四、总结

本篇文章我们深入分析了String字符串的内存分配、intern()方法,以及String类的结构及特性。关于这块知识,网上的文章鱼龙混杂,甚至众说纷纭。笔者也是参考了大量的文章并结合自己的理解来做的分析。但是,避免不了的可能会出现理解偏差的问题,如果有,希望大家多多讨论给予指正。 同时,文章中多次提到StringBuilder,但限于文章篇幅,没能给出关于其详细分析。不过不用担心,我会在下一篇文章中再做探讨。 不管怎样,相信大家看完这篇文章后一定 对String有了更加深入的认识,尤其是了解String类的一些裁剪及拼接中可能造成的性能问题,在今后的开发中应该尽量避免。


以上が過去を振り返り、新しいことを学ぶ (1) Javaの文字列を深く理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

PHP対Python:違いを理解します PHP対Python:違いを理解します Apr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

PHP:Web開発の重要な言語 PHP:Web開発の重要な言語 Apr 13, 2025 am 12:08 AM

PHPは、サーバー側で広く使用されているスクリプト言語で、特にWeb開発に適しています。 1.PHPは、HTMLを埋め込み、HTTP要求と応答を処理し、さまざまなデータベースをサポートできます。 2.PHPは、ダイナミックWebコンテンツ、プロセスフォームデータ、アクセスデータベースなどを生成するために使用され、強力なコミュニティサポートとオープンソースリソースを備えています。 3。PHPは解釈された言語であり、実行プロセスには語彙分析、文法分析、編集、実行が含まれます。 4.PHPは、ユーザー登録システムなどの高度なアプリケーションについてMySQLと組み合わせることができます。 5。PHPをデバッグするときは、error_reporting()やvar_dump()などの関数を使用できます。 6. PHPコードを最適化して、キャッシュメカニズムを使用し、データベースクエリを最適化し、組み込み関数を使用します。 7

未来を創る: まったくの初心者のための Java プログラミング 未来を創る: まったくの初心者のための Java プログラミング Oct 13, 2024 pm 01:32 PM

Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。

See all articles