Java基本程序设计结构

Posted 面向丈母娘编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基本程序设计结构相关的知识,希望对你有一定的参考价值。

1.一个简单的Java程序

public class Test {
    public static void main(String[] args) {
        System.out.println("==============args start============");
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
        System.out.println("==============args end============");
        System.out.println("args: " + args);
    }
}

在Java语言中,规定了入口函数是一个main()方法,该方法有一个String[]类型的参数,但是在很多时候,很多人都使用不上这个参数,也不关心为什么要写这个参数。

那么这个字符串数组类型的参数究竟是什么东西呢?

其实很简单,main()方法中的字符串数组类型的参数就是java命令的参数,使用java命令的方式运行main()方法,会将java命令的参数入参到Java main()方法的字符串数组参数中。

我们通过以下方式来验证:

  1. 先编写一个Hello.java文件,文件内容如下:
public class Test {
    public static void main(String[] args) {
        System.out.println("==============args start============");
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
        System.out.println("==============args end============");
        System.out.println("args: " + args);
    }
}
  1. Test.java文件的路径下打开cmd命令提示符,运行javac -encoding utf-8 Test.java命令编译该文件,这将会在对应的文件路径下,得到一

个Test.class字节码文件。

当文件中出现中文的时候,比如输出的内容有汉字的时候需要使用utf-8编码,加上了编码格式,保证后续命令行编译输出没有乱码情况

  1. 使用java Test命令运行Test.class文件,我们将会得到如下的运行结果:
  2. 我们这次在java命令后面添加一些参数,这些参数我们可以自己定义。
    例如:java Test a b c d我们将会得到如下的运行结果:

正是因为Java main()方法的这个扩展性,使得每一个开发者,可以通过自己定义一些Java命令的参数,实现一些不同的功能。

2.注释

2.1 普通注释

这些注释用一个 “/*” 起头,随后是注释内容,并可跨越多行,最后用一个“/”结束

/* 这是
*一段注释,
* 它跨越了多个行
*/

进行编译时,// 之间的所有东西都会被忽略,所以上述注释与下面这段注释并没
有什么不同

/* 这是一段注释,
它跨越了多个行 */

// 这是一条单行注释

2.2 嵌入文档

用于提取注释的工具叫作 javadoc。它采用了部分来自Java编译器的技术,查找我们置入程序
的特殊注释标记。它不仅提取由这些标记指示的信息,也将毗邻注释的类名或方法名提取出
来。这样一来,我们就可用最轻的工作量,生成十分专业的程序文档。
所有javadoc命令都只能出现于 /** 注释中。但和平常一样,注释结束于一个 */ 。主
要通过两种方式来使用javadoc:嵌入的html,或使用“文档标记”。其中,“文档标记”(Doc
tags)是一些以“@”开头的命令,置于注释行的起始处(但前导的*会被忽略)

/** 一个类注释 /
public class docTest {
/
* 一个变量注释 /
public int i;
/
* 一个方法注释 */
public void f() {}
}

嵌入HTML
/**
* <pre>
* System.out.println(new Date());
* </pre>
*/

/**
* 您甚至可以插入一个列表:
*\\


  1. * <li> 项目一
    * <li> 项目二
    * <li> 项目三
    * </ol>
    */

引用其它类
@see 类名
@see 完整类名
@see 完整类名#方法名

类文档标记
@version 版本信息
@author 作者信息

变量文档标记
变量文档只能包括嵌入的HTML以及@see引用

方法文档标记
. @param 格式如下: @param 参数名 说明 其中,“参数名”是指参数列表内的标识符,
而“说明”代表一些可延续到后续行内的说明文字。一旦遇到一个新文档标记,就认为前一个说
明结束。可使用任意数量的说明,每个参数一个。
@return 说明
@exception 完整类名 说明【它们是一些特殊的对
象,若某个方法失败,就可将它们“扔出”对象】

注意javadoc只能为 public(公共)和 protected(受保护)成员处理注释文档。“private”(私
有)和“友好”成员的注释会被忽略,我们看不到任何输出(也可以用-private标记
包括private成员)。因为只有public和protected成员才可在文件之外使
用。

3. 编码样式

  1. 一个非正式的Java编程标准是大写一个类名的首字母。若类名由几个单词构成,那么把它们
    紧靠到一起(也就是说,不要用下划线来分隔名字)。此外,每个嵌入单词的首字母都采用
    大写形式
  2. 对于其他几乎所有内容:方法、字段(成员变量)以及对象句柄名称,可接受的样式与类样
    式差不多,只是标识符的第一个字母采用小写。
    举例:
class AllTheColorsOfTheRainbow {
    int anIntegerRepresentingColors;

    void changeTheHueOfTheColor(int newHue) {
// ...
    }
// ...
}

4.基础数据类型【口诀:4类8种】

4.1 整型


在 C 和 C++ 中, int 和 long 等类型的大小与目标平台相关。在 8086 这样的16 位处理器上整型数值占 2 字节;不过, 在 32 位处理器上,整型数值则为 4 字节。 类似地, 在 32 位处理器上 long 值为 4 字节, 在 64 位处理器上则为 8 字节。由于存在这些差别, 这对编写跨平台程序带来了很大难度。 在 Java 中, 所有的数值类型所占据的字节数量与平台无关。
注意, Java 没有任何无符号(unsigned) 形式的 int、 long、short 或 byte 类型。

在通常情况下,int 类型最常用。但如果表示星球上的居住人数, 就需要使用 long 类型 了。byte 和 short
类型主要用于特定的应用场合,例如,底层的文件处理或者需要控制占用 存储空间量的大数组。

长整型数值有一个后缀 L 或 1 ( 如 4000000000L。) 十六进制数值有一个前缀 Ox 或 0X (如 OxCAFEL
八进制有一个前缀 0 , 例如, 010 对应八进制中的 8。很显然, 八进制表示法比较容易混淆, 所以建议最好不要使用八进制常数

从 Java 7 开始, 加上前缀 0b 或 0B 就可以写二进制数。例如,OblOO丨就是 9。 另外,同样是从 Java 7
开始,还可以为数字字面量加下划线,如用 1_000_000(或0b1111 0100 0010 0010 0000)表示一百万。这些下划线只是为了让人更易读。Java 编译器会去除这些下划线

4.2 浮点型

double 表示这种类型的数值精度是 float 类型的两倍(有人称之为双精度数值)。绝大部 分应用程序都采用 double类型。在很多情况下,float 类型的精度很难满足需求。实际上,只 有很少的情况适合使用 float 类型,例如,需要单精度数据的库,或者需要存储大量数据。 float 类型的数值有一个后缀 F 或 f (例如,3.14F。) 没有后缀 F 的浮点数值(如 3.14 ) 默认为 double 类型。当然,也可以在浮点数值后面添加后缀 D 或 d (例如,3.14D) 。
浮点数值不适用于无法接受舍入误差的金融计算中。 例如,命令 System.out.println( 2.0-1.1 ) 将打印出 0.8999999999999999, 而不是人们想象的 0.9。这种舍入误差的主要原因是浮点数值采用二进制系统表示, 而在二进制系统中无法精确地表示分数 1/10。这就好像十进制无法精确地表示分数 1/3—样。如果在数值计算中不允许有任何舍入误差,就应该使用 BigDecimal类

4.3 char 类型

char 类型原本要用单引号括起来于表示单个字符。不过,现在情况已经有所变化。 如今,有些 Unicode 字符可以用一个 char 值描述,另外一些 Unicode 字符则需要两个 char 值。char 类型的值可以表示为十六进制值,其范围从 \\u0000 到 \\Uffff。例如:W2122 表示注册符号 (® ), \\u03C0 表示希腊字母 Π

Unicode 转义序列会在解析代码之前得到处理。 例如,"\\u0022+\\u0022”并不是一个由引号(U+0022)包围加号构成的字符串。 实际上, \\u0022 会在解析之前转换为 ", 这会 得 到 也 就 是 一 个 空 串。更隐秘地,一定要当心注释中的 \\u。 注释// \\u00A0 is a newline 会产生一个语法错误, 因为读程序时\\u00A0会替换为一个换行符类似地,下面这个注释 // Look inside c:\\users 也会产生一个语法错误, 因为 \\u> 后面并未跟着 4 个十六进制数

要想弄清 char 类型, 就必须了解 Unicode 编码机制。Unicode 打破了传统字符编码机制
的限制。
历史原因:在 Unicode 出现之前, 已经有许多种不同的标准:美国的 ASCII、 西欧语言中的ISO 8859-1 俄罗斯的 KOI-8、 中国的 GB 18030 和 BIG-5 等。这样就产生了下面两个问题:一个是对于任意给定的代码值,在不同的编码方案下有可能对应不同的字母;二是采用大字符集的语言其编码长度有可能同。例如,有些常用的字符采用单字节编码, 而另一些字符则需要两个或更多个字节。

改进:在设计 Java 时决定采用 16 位的 Unicode 字符集,这样会比使用 8 位字符集的程序设计语言有很大的改进。十分遗憾, 经过一段时间, 不可避免的事情发生了。Unicode 字符超过了 65 536 个,其主要原因是增加了大量的汉语、 日语和韩语中的表意文字。现在,16 位的 char 类型已经不能满足描述所有 Unicode 字符的需要了。

以下是维基百科内容:
16位的 cha r如何描述所有 Unicode 字符

从 Java SE 5.0 开始。码点( code point) 是指与一个编码表中的某个字符对应的代码值。在 Unicode标准中,码点采用十六进制书写,并加上前缀 U+, 例如 U+0041 就是拉丁字母 A 的码点。Unicode 的码点可以分成 17个代码级别( codeplane)。第一个代码级别称为基本的多语言级别( basicmultilingual plane ), 码点从U+0000 到U+FFFF, 其中包括经典的 Unicode 代码;其余的 16个级另丨〗码点从 U+10000 到 U+10FFFF ,其中包括一些辅助字符(supplementary character)。UTF-16 编码采用不同长度的编码表示所有 Unicode码点。在基本的多语言级别中,每个字符用 16 位表示,通常被称为代码单元( code unit); 而辅助字符采用一对连续的代码单元进行编码。这样构成的编码值落人基本的多语言级别中空闲的 2048 字节内,通常被称为替代区域(surrogate area) [ U+D800 ~ U+DBFF 用于第一个代码单兀,U+DC00 ~ U+DFFF用于第二个代码单元。这样设计十分巧妙,我们可以从中迅速地知道一个代码单元是一个字符的编码,还是一个辅助字符的第一或第二部分。例如,⑪是八元数(http://math.ucr.edu/home/baez/octonions) 的一个数学符号,码点为 U+1D546, 编码为两个代码单兀 U+D835 和U+DD46。(关于编码算法的具体描述见http://en.wikipedia.org/wiki/UTF-l6 )

强烈建议不要在程序中使用 char 类型,除非确实需要处理 UTF-16 代码单元。最好 将字符串作为抽象数据类型处理

4.4 boolean 类型

boolean (布尔)类型有两个值:false 和 true, 用来判定逻辑条件 整型值和布尔值之间
不能进行相互转换。

在 C++ 中, 数值甚至指针可以代替 boolean 值。值 0 相当于布尔值 false, 非 0 值相当于布尔值 true, 在
Java 中则不是这样,, 因此, Java 程序员不会遇到下述麻烦:
if (x = 0) // oops… meant x = 0
在 C++ 中这个测试可以编译运行, 其结果总是 false: 而在 Java 中, 这个测试将不 能通过编译, 其原因是整数表达式 x = 0 不能转换为布尔值。

5.变量

5.1 可以在一行中声明多个变量:

不能使用 Java 保留字作为变量名

int i , j; // both are integers

5.2 变量初始化

声明一个变量之后,必须用赋值语句对变量进行显式初始化, 千万不要使用未初始化的
变量。例如, Java 编译器认为下面的语句序列是错误的

int vacationDays;
System.out.println(vacationDays): // ERROR variable not initialized

C 和 C++ 区分变量的声明与定义。例如:
int i = 10; 是一个定义
而 extern int i; 是一个声明。
在 Java中, 不区分变量的声明与定义。

5.3 常量

在 Java 中, 利用关键字 final 指示常量。例如:

public class Test {
    public static void main(String[] args) {
        final double CM_PER_INCH = 2.54;
        double paperWidth = 8.5;
        double paperHeight = 11;
        System.out.println("Paper size in centimeters: "
                + paperWidth * CM_PER_INCH + "by" + paperHeight * CM_PER_INCH);
    }
}
//Paper size in centimeters: 21.59by27.94

在 Java 中,经常希望某个常量可以在一个类中的多个方法中使用,通常将这些常量称为
类常量。可以使用关键字 static fina丨设置一个类常量。 下面是使用类常量的示例:

public class Test {
    public static final double CM_PER_INCH2 = 2.54;

    public static void main(String[] args) {
        double paperWidth = 8.5;
        double paperHeight = 11;
        System.out.println("Paper size in centimeters: "
                + paperWidth * CM_PER_INCH2 + "by" + paperHeight * CM_PER_INCH2);
    }
}
//Paper size in centimeters: 21.59by27.94

需要注意, 类常量的定义位于 maiii 方法的外部。因此,在同一个类的其他方法中也可
以使用这个常量。而且,如果一个常量被声明为 public,那么其他类的方法也可以使用这个
常量。 在这个示例中,Constants2.CM_PER-INCH 就是这样一个常童。

6.运算符

6.1 可移植性和性能间的平衡

需要严格计算【了解】 很多 Intel 处理器计算 x * y,并且将结果存储在 80 位的寄存器中, 再除以 z 并将结果截断为 64 位„ 这样可以得到一个更加精确的计算结果,并且还能够避免产生指数溢出。但是, 这个结果可能与始终在 64 位机器上计算的结果不一样。 因此,Java 虚拟机的最初规范规定所有的中间计算都必须进行截断这种行为遭到了数值计算团体的反对。截断计算不仅可能导致溢出, 而且由于截断操作需要消耗时间, 所以在计算速度上实际上要比精确计算慢。 为此,Java程序设计语言承认了最优性能与理想结果之间存在的冲突,并给予了改进。在默认情况下, 虚拟机设计者允许对中间计算结果采用扩展的精度。但是,对于使用 strictfj) 关键字标记的方法必须使用严格的浮点计算来生成可再生的结果。例如,可以把 main 方法标记为:
publicstatic strictfp void main(String[] args)
于是,在 main 方法中的所有指令都将使用严格的浮点计算。如果将一个类标记为strictfp,这个类中的所有方法都要使用严格的浮点计算。实际的计算方式将取决于 Intel 处理器的行为。在默认情况下,中间结果允许使用扩展的指数,但不允许使用扩展的尾数(Intel 芯片在截断尾数时并不损失性能)。因此,这两种方式的区别仅仅在于采用默认的方式不会产生溢出,而采用严格的计算有可能产生溢出对大多数程序来说, 浮点溢出不属于大向题。

6.2常用数学函数

double y = Math.sqrt(3.14);//开平方,形参是double类型,返回值也是double类型
double y = Math.pow(x, a);//幂运算将,形参是double类型,返回值也是double类型

Math 类提供了一些常用的三角函数:

Math.sin
Math.cos
Math.tan
Math.atan
Math.atan2

有指数函数以及它的反函数—自然对数以及以 10 为底的对数:

Math.exp
Math.log
Math.loglO

最后,Java 还提供了两个用于表示 TC 和 e 常量的近似值:

Math.PI
Math.E

小技巧:不必在数学方法名和常量名前添加前缀“ Math”, 只要在源文件的顶部加上下面
这行代码就可以了。

import static java.lang.Math.*;
System.out.println("The square root of \\u03C0 is " + sqrt(PI));

精度和性能:在 Math 类中, 为了达到最快的性能, 所有的方法都使用计算机浮点单元中的例
程… 如果得到一个完全可预测的结果比运行速度更重要的话, 那么就应该使用 StrictMath

6.3 数值类型之间的转换

某些整型数值转换为 float 类型时, 将会得到同样大小的结果,但却失去了一定
的精度

        int n = 123456789;
        float f = n; // f is 1.23456792E
        System.out.println("n: " + n);
        System.out.println("f: " + f);
        System.out.printf("格式化输出f: %f\\n", f);
        //n: 123456789
		//f: 1.23456792E8
		//格式化输出f: 123456792.000000
		//float ff = 3.14;//编译报错原因:因为小数会自动隐式提升到 double, 因此需要在小数后加上F或者f
        float ff = 3.14f;

转换规则:当使用上面两个数值进行二元操作时(例如 n + f,n 是整数, f 是浮点数,) 先要将两个操作数转换为同一种类型,然后再进行计算。

  • 如果两个操作数中有一个是 double 类型, 另一个操作数就会转换为 double 类型。
  • 否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float 类型。
  • 否则, 如果其中一个操作数是 long 类型, 另一个操作数将会转换为 long 类型。
  • 否则, 两个操作数都将被转换为 int 类型

6.4 强制类型转换

		byte b1 = 1;
        byte b2 = 2;
        byte b3 = (byte) (b1+b2);//编译报错原因:byte类型会隐式提升为 int,因此需要类型强转
        int i1= (int) Math.round(3.14);//其原因是 round 方法返回的结果为 long 类型,由于存在信息丢失的可能性,所以只有使用显式的强制类型转换才能够将 long 类型转换成 int 类型。

如果试图将一个数值从一种类型强制转换为另一种类型, 而又超出了目标类型的表示范围,结果就会截断成一个完全不同的值。例如,(byte )> 300 的实际值为 44

     	System.out.println("byte取值范围: [" + Byte.MAX_VALUE + ", " + Byte.MIN_VALUE + "]");
        System.out.println("(byte)128: " + (byte) 128);
        System.out.println("(byte)(-129): " + (byte) (-129));
        //byte取值范围: [127, -128]
		//(byte)128: -128
		//(byte)(-129): 127
       	System.out.println(Integer.MAX_VALUE);//System.out.println()默认内部数据类型是 int,超出范围即溢出
        System.out.println(Integer.MAX_VALUE+1);
        System.out.println(Integer.MIN_VALUE);
        System.out.println(Integer.MIN_VALUE-1);
        //2147483647
		//-2147483648
		//-2147483648
		//2147483647


附加

不要在 boolean 类型与任何数值类型之间进行强制类型转换, 这样可以防止
发生错误。只有极少数的情况才需要将布尔类型转换为数值类型,这时可以使用条件表 达式 b ? 1:0

6.5 优先级

  • % 表示取余, 不仅仅可以对 int 求模, 也能对 double 来求模
  • &&,||会出现短路运算
  • 左移 <<: 最左侧位不要了, 最右侧补 0【 左移 1 位, 相当于原数字 * 2. 左移 N 位, 相当于原数字 * 2 的N次方.】
  • 右移 >>: 最右侧位不要了, 最左侧补符号位(正数补0, 负数补1)【右移 1 位, 相当于原数字 / 2. 右移 N 位, 相当于原数字 / 2 的N次方.】
  • 无符号右移 >>>: 最右侧位不要了, 最左侧补 0.
  • 没有无符号左移<<<
  • 由于计算机计算移位效率高于计算乘除, 当某个代码正好乘除 2 的N次方的时候可以用移位运算代替.移动负数位或者移位位数过大都没有意义

System.out.println(10 < 20 && 20 < 30); 虽然关系运算符优先级高于逻辑运算符但此时明显是先计算的 10< 20 和 20 < 30, 再计算 &&. 否则 20 && 20 这样的操作是语法上有误的(&& 的操作数只能是 boolean).

6.6 结合赋值和运算符

可以在赋值中使用二元运算符,这是一种很方便的简写形式。例如:
X += 4;
等价于:
x = x + 4;
(一般地, 要把运算符放在 = 号左边,如 *=,%=,/=,-=,<<=,>>=,>>>=,&=, |=,,^=)

6.7 自增与自减运算

int n = 12;
n++;

将 n 的值改为 13。由于这些运算符会改变变量的值,所以它们的操作数不能是数值。例如,
4++ 就不是一个合法的语句。实际上, 这些运算符有两种形式;上面介绍的是运算符放在操作数后面的“ 后缀” 形式。还有一种“ 前缀” 形式:++n。后缀和前缀形式都会使变量值加 1 或减 1。但用在表达式中时,二者就有区别了。前缀形式会先完成加 1; 而后缀形式会使用变量原来的值。
int m = 7;
int n = 7;
int a = 2 * ++m; // now a is 16, m is 8
int b = 2 * n++; // now b is 14, n is 8
建议不要在表达式中使用 ++, 因为这样的代码很容易让人闲惑,而且会带来烦人的 bug。

6.8 枚举类型

public class Test {
    enum Size {SMALL, MEDIUM, LARGE, EXTRA};
    public static void main(String[] args) {
        Size s = Size.MEDIUM;
        System.out.println(s);
    }
}
//MEDIUM

7.字符串

从概念上讲, Java 字符串就是 Unicode 字符序列。 例如, 串“ Java\\u2122” 由 5 个Unicode 字符 J、a、 v、a 和™。Java 没有内置的字符串类型, 而是在标准 Java 类库中提供了一个预定义类,很自然地叫做 String。每个用双引号括起来的字符串都是 String类的一个实
例:

public class Test {
    public static void main(String[] args) {
        String str = "";
        String str1 = null;
        String str2 = "Hello World";
        System.out.println(str);
        System.out.println(str1);
        System.out.println(str2);
    }
}
//
//null
//Hello World

7.1 子串

public class Test {
    public static void main(String[] args) {
        String greeting = "Hello";
        String s = greeting.substring(0, 3);
        System.out.println(s);
    }
}
//Hel

substring 方法的第二个参数是不想复制的第一个位置。这里要复制位置为 0、 1 和 2 (从 0 到 2, 包括 0 和 2 )
的字符。在 substring 中从 0 开始计数,直到 3 为止, 但不包含 3

7.2 拼接

public class Test {
    public static void main(String[] args) {
        String expletive = "Expletive";
        String PC13 = "deleted";
        String message = expletive + PC13;
        System.out.println(message);
    }
}
//Expletivedeleted

+ 号连接(拼接)两个字符串,“ Expletivedeleted” 赋给变量 message

当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串

public class Test {
    public static void main(String[] args) {
        int age = 13;
        String rating = "PC" + age;
        System.out.println(rating);
    }
}
//PC13

这种特性通常用在输出语句中。例如:System.out.println("The answer is " + answer);
如果需要把多个字符串放在一起, 用一个定界符分隔,可以使用静态 join 方法

public class Test {
    public static void main(String[] args) {
        String all = String.join(" / ", "S", "M", "L", "XL");
        System.out.println(all);
    }
}
//S / M / L / XL

7.3 不可变字符串

String 类没有提供用于修改字符串的方法。 如果希望将 src的内容修改为“ Hello Java!”,不能直接地将 greeting 的最后位置的字符修改为‘Java ’ 和 ‘!’ 这对于 C 语言来说,将会感到无从下手。如何修改这个字符串呢? 在 Java中实现这项操作非常容易。首先提取需要的字符, 然后再拼接上替换的字符串

public class Test {
    public static void main(String[] args) {
        String src = "Hello World";
        src = src.substring(0, 5) + " Java!";
        System.out.println(src);
    }
}
//Hello Java!

理解 String 类不可变:

由于不能修改 Java 字符串中的字符, 所以在 Java 文档中将 String 类对象称为不可变字 符串, 如同数字 3 永远是数字 3—样,字符串“ Hello” 永远包含字符 H、 e、1、 1 和 o 的代 码单元序列, 而不能修改其中的任何一个字符。当然, 可以修改字符串变量 src, 让它 引用另外一个字符串, 这就如同可以将存放 3 的数值变量改成存放 4 一样

思考

这样做是否会降低运行效率呢? 看起来好像修改一个代码单元要比创建一个新字符串更 加简洁。答案是:也对,也不对。的确, 通过拼接“ Hello” 和“ Java! ” 来创建一个新字符串的 效率确实不高。但是,不可变字符串却有一个优点:编译器可以让字符串共享。为了弄清具体的工作方式,可以想象将各种字符串存放在公共的存储池中。字符串变量 指向存储池中相应的位置。如果复制一个字符串变量,原始字符串与复制的字符串共享相同 的字符。 总而言之,Java 的设计者认为共享带来的高效率远远胜过于提取、 拼接字符串所带来的 低效率

学 C 的同学第一次接触 Java 字符串的时候, 常常会感到迷惑, 因为他们总将字符串认为是字符型数组:

char greeting[ ] = "Hello";
//这种认识是错误的, Java 字符串大致类似于 char* 指针,
char* src= "Hello World";
//当采用另一个字符串替换 src 的时候, Java 代码大致进行下列操作:
char* temp = mal1oc(11);
strncpy(temp, src, 5);
strncpy(temp + 1, "Java!, 3);
src= temp;

Java 角度考虑这样做会不会产生内存遗漏呢? 毕竞, 原始字符串放置在堆中。十分幸运,强大的 JVM 将自动地进行垃圾回收。 如果一块内存不再使用了, 系统最终会将其回收。

有了前边的理论知识下面一幅图解释清楚不可变
字符串是一种不可变对象. 它的内容不可改变.String

以上是关于Java基本程序设计结构的主要内容,如果未能解决你的问题,请参考以下文章

hashmap冲突的解决方法以及原理分析:

介绍下Java程序的结构

大厂面试必问!HashMap 怎样解决hash冲突?

Java核心技术-Java的基本程序设计结构

Java基本程序结构

for循环结构