java语言概述
Java是一种高级编程语言,最初由Sun Microsystems(现在是Oracle Corporation的一部分)在1995年推出。Java以其简单、可移植和安全的特性而闻名,并广泛用于各种应用程序开发,从桌面应用程序到移动应用程序和企业级应用程序。
2009 年 04 月 20 日,美国甲骨文公司 74 亿美元收购 Sun,取得 java 的版权。
Java 不只是一种编程语言,它是一个完整的平台,拥有庞大的库,将诸如图形绘制、Socket连接、数据库存取等复杂操作进行了最大程度的简化。
Java的特点之一是其跨平台性。Java程序可以在不同的操作系统上运行,包括Windows、Mac和Linux等。这得益于Java虚拟机(JVM),它充当了一个中间层,将Java代码转换为特定平台上的可执行文件。这种可移植性使得Java成为开发跨平台应用程序的理想选择。
在世界编程语言排行榜中,Java占据着第三名的位置,仅次于C语言。
Java是典型的面向对象的语言,晚于C++发布,部分语法和思想也参考了C++:
尽管人们发现C++的语法太复杂,有很多冗余,但是 Java 在设计的时候还是尽可能的接近C++,降低人们的学习成本。Java 语法是 C++ 语法的一个“纯净”版,没有头文件、指针运算(也没有指针语法)、结构、联合、运算符重载、虚基类等。有C++基础的读者,可以轻易地切换到Java。
此外,Java也被广泛用于Android应用程序的开发。Android平台使用Java作为其主要编程语言,开发者可以利用Java的语法和库来构建功能丰富的移动应用程序。
总的来说,Java是一种多功能、可移植和易于学习的编程语言,适用于各种应用程序开发,并在企业级和移动应用开发领域广泛应用。它的跨平台性、面向对象的设计和强大的库支持使得Java成为众多开发人员的首选语言之一。
一、第一个java程序
程序员的第一站:HELLO WORD
public class Hello{ //定义一个名为Hello的类( public static void main(String[] args){ //main入口 System.out.println("Hello World"); //打印输出Hello World } }
执行可以看到输出结果
二、数据类型
Java 是一种强类型的语言,声明变量时必须指明数据类型。变量(variable)的值占据一定的内存空间。不同类型的变量占据不同的大小。
- 常量:在程序的执行过程中,其值不会发生改变的量(数据)。
- 变量:就是内存中的存储空间,空间中存储着经常发生改变的值。
- 基本数据类型
- 引用数据类型:除了上述8种基本数据类型,其余的都是引用数据类型(引用类型存放在堆里,基本类型存放在栈里)
Java中共有8种基本数据类型,包括4 种整型、2 种浮点型、1 种字符型、1 种布尔型
数据类型 说明 所占内存 举例 备注 byte 字节型 1 byte 3, 127 short 短整型 2 bytes 3, 32767 int 整型 4 bytes 3, 21474836 long 长整型 8 bytes 3L, 92233720368L long最后要有一个L字母(大小写无所谓)。 float 单精度浮点型 4 bytes 1.2F, 223.56F float最后要有一个F字母(大小写无所谓)。 double 双精度浮点型 8 bytes 1.2, 1.2D, 223.56, 223.56D double最后最好有一个D字母(大小写无所谓)。 char 字符型 2 bytes 'a', ‘A’ 字符型数据只能是一个字符,由单引号包围。 boolean 布尔型 1 bit true, false
三、数据类型的转换
在Java中,数据类型的转换是将一个数据类型的值转换为另一个数据类型的过程。Java提供了两种类型的数据类型转换:隐式转换(自动转换)和显式转换(强制转换)。
- 隐式转换(自动转换): 隐式转换是指将一个小范围的数据类型自动转换为一个大范围的数据类型。在这种情况下,Java会自动执行类型转换,不需要显式地编写代码来执行转换。例如,将一个整数赋值给一个浮点数变量:
int num1 = 10; double num2 = num1; // 隐式转换,将int类型转换为double类型 System.out.println(num2); // 输出结果为 10.0
在上述示例中,整数类型的变量
num1
被隐式转换为浮点数类型的变量num2
。
- 显式转换(强制转换): 显式转换是指将一个大范围的数据类型手动转换为一个小范围的数据类型。在这种情况下,需要使用强制转换操作符(
()
)来显式地将一个数据类型转换为另一个数据类型。例如,将一个浮点数赋值给一个整数变量:double num1 = 10.5; int num2 = (int) num1; // 显式转换,将double类型转换为int类型 System.out.println(num2); // 输出结果为 10
在上述示例中,浮点数类型的变量
num1
被显式转换为整数类型的变量num2
。需要注意的是,当执行显式转换时,可能会发生数据丢失或溢出。例如,将一个大范围的整数转换为一个小范围的整数时,可能会导致溢出。因此,在进行显式转换之前,应该确保转换是安全的。
四、java运算符
Java中的运算符和C/C++相差无几,是对常量或者变量进行操作的符号。
数学运算符
数学运算,结果为一个数值。见下表:
运算符 说明 举例 + 加法 1 + 2 - 减法 4 - 3.4 * 乘法 7 * 1.5 / 除法 3.5 / 7 % 取余 7 % 2 ++ 自增 3++ -- 自减 3--
public static void main(String[] args) { // 算术运算符示例 int num1 = 10; int num2 = 5; int sum = num1 + num2; int difference = num1 - num2; int product = num1 * num2; int quotient = num1 / num2; int remainder = num1 % num2; System.out.println("Sum: " + sum); System.out.println("Difference: " + difference); System.out.println("Product: " + product); System.out.println("Quotient: " + quotient); System.out.println("Remainder: " + remainder); }
关系运算符
关系运算符,结果为一个布尔值。见下表:
运算符 说明 举例 > 大于 a > 4.2 >= 大于等于 3.4 >= b < 小于 1.5 < 9 <= 小于等于 6 <= 1 == 等于 2 == 2 != 不等于 2 != 2 && 与 true && false || 或 (3 > 1) || (2 == 1) ! 非 !true // 比较运算符示例 int a = 5; int b = 10; boolean isEqual = (a == b); boolean isNotEqual = (a != b); boolean isGreater = (a > b); boolean isLess = (a < b); boolean isGreaterOrEqual = (a >= b); boolean isLessOrEqual = (a <= b); System.out.println("isEqual: " + isEqual); System.out.println("isNotEqual: " + isNotEqual); System.out.println("isGreater: " + isGreater); System.out.println("isLess: " + isLess); System.out.println("isGreaterOrEqual: " + isGreaterOrEqual); System.out.println("isLessOrEqual: " + isLessOrEqual);
位运算符
位运算符对整数的二进制形式逐位进行逻辑运算,得到一个整数。见下表:
运算符 说明 举例 & 与 1 & 4 | 或 2 | 5 ^ 异或 2 ^ 3 ~ 非 ~5 << 左移 5 << 3 >> 右移 6 >> 1 // 逻辑运算符示例 boolean p = true; boolean q = false; boolean logicalAnd = p && q; boolean logicalOr = p || q; boolean logicalNot = !p; System.out.println("logicalAnd: " + logicalAnd); System.out.println("logicalOr: " + logicalOr); System.out.println("logicalNot: " + logicalNot); }
四、流程控制
通过一些语句,来控制程序的执行流程,Java流程控制的语法与 C/C++ 类似,也有 if...else、while、do...while、for、switch...case等
顺序结构语句:程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序依次执行,程序中大多数代码都是这样的
1、if语句
if(关系表达式){ 语句体1; }else{ 语句体2; }
执行流程
- 首先计算关系表达式的值
- 如果关系表达式的值为true则执行语句体1
- 如果关系表达式为false就执行语句体2
- 继续执行后续代码
import java.util.Scanner; public class a{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); System.out.println("请输入您的年龄:"); int age = sc.nextInt(); if(age >= 18){ System.out.println("您已成年"); }else{ System.out.println("您未成年"); } } }
如果if语句中的语句体只有一条,那么大括号{}可以省略不写,但是不建议,容易混淆 if语句小括号后面不要写分号;
多条件判断:
基本语法:
if(判断条件){ 语句体1; }else if(判断条件2){ 语句体2; } ... else{ 语句体n+1; }
代码示例:
public class a{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); System.out.println("请输入您的成绩:"); int score = sc.nextInt(); if(score >= 90 && score <= 100){ System.out.println("优秀"); }else if(score >= 80 && score < 90){ System.out.println("良好"); }else if(score >=60 && score < 80){ System.out.println("及格"); }else if(score <60 && score >= 0){ System.out.println("不及格"); }else{ System.out.println("请输入正确的成绩!"); } } }
2、switch语句
当需要根据不同的条件执行不同的代码块时,可以使用Java中的
switch
语句。switch
语句根据给定的表达式的值,选择匹配的case
语句执行相应的代码块语法:
switch(表达式){ case 值1: 语句体1; break; case 值2; 语句体2; break; .... default: 语句体n+1; break; }
格式说明
- 表达式(将要被匹配的值)取值为byte、short、int、char、枚举(jdk5)、String(jdk7)
- case:后面跟的是要和表达式比较的值(被匹配的值)
- break:表示中断,结束的意思,用来结束switch语句
- default:表示所有的情况都不匹配的时候,就执行该处的内容,和if语句的else相似
案例:
public class SwitchExample { public static void main(String[] args) { int dayOfWeek = 4; // 假设今天是星期四 switch (dayOfWeek) { case 1: System.out.println("今天是星期一"); break; case 2: System.out.println("今天是星期二"); break; case 3: System.out.println("今天是星期三"); break; case 4: System.out.println("今天是星期四"); break; case 5: System.out.println("今天是星期五"); break; case 6: System.out.println("今天是星期六"); break; case 7: System.out.println("今天是星期日"); break; default: System.out.println("无效的星期几"); break; } } }
3、for循环
推荐在明确循环次数时使用
当需要重复执行一段代码块固定次数或基于条件时,可以使用Java中的
for
循环结构。for
循环由三个部分组成:初始化语句、循环条件和循环迭代语句语法:
for(初始化语句;条件判断语句;条件控制语句){ 循环体语句; }
public class ForLoopExample { public static void main(String[] args) { // 循环执行5次 for (int i = 1; i <= 5; i++) { System.out.println("循环次数:" + i); } System.out.println(); // 根据数组长度循环遍历数组元素 int[] numbers = {1, 2, 3, 4, 5}; for (int i = 0; i < numbers.length; i++) { System.out.println("数组元素:" + numbers[i]); } System.out.println(); // 根据条件循环执行代码块 int counter = 0; for (; counter < 3; ) { System.out.println("计数器值:" + counter); counter++; } } }
在上述示例中,展示了几种使用
for
循环的情况。第一个for
循环示例是一个固定次数的循环,重复执行5次,输出循环次数。第二个for
循环示例是基于数组的循环,通过迭代变量i
访问数组元素并输出。第三个for
循环示例是根据条件循环执行代码块,计数器初始值为0,每次循环递增1,直到计数器的值小于3为止。你可以根据需要修改和扩展示例代码。
for
循环是Java中最常用的循环结构之一,用于重复执行一段代码块,具有很高的灵活性和适应性。4、while循环
不明确循环次数时推荐while
当需要根据条件重复执行一段代码块时,可以使用Java中的
while
循环结构。while
循环在每次循环迭代之前检查循环条件是否为真,如果条件为真,则执行循环体内的代码块语法:
while(条件判断语句){ 循环体语句; 条件控制语句; }
案例:
public class WhileLoopExample { public static void main(String[] args) { // 循环执行5次 int counter = 1; while (counter <= 5) { System.out.println("循环次数:" + counter); counter++; } System.out.println(); // 根据条件循环执行代码块 int number = 0; while (number < 10) { System.out.println("当前数字:" + number); number += 2; } } }
在上述示例中,展示了两种使用
while
循环的情况。第一个while
循环示例是一个固定次数的循环,重复执行5次,输出循环次数。循环之前初始化计数器为1,每次循环迭代后计数器递增。第二个while
循环示例是根据条件循环执行代码块,初始数字为0,每次循环迭代后数字递增2,直到数字达到10为止。你可以根据需要修改和扩展示例代码。
while
循环是一种常用的循环结构,用于根据条件重复执行代码块,灵活性较高。5、do...while循环
使用较少
语法:
do{ 循环体语句; 条件控制语句; }while(条件判断语句);
三种循环的区别:
for
循环:
for
循环是一种在已知循环次数的情况下使用的循环结构。它由初始化语句、循环条件和循环迭代语句组成。- 初始化语句用于初始化循环变量,循环条件用于判断是否继续循环,循环迭代语句用于更新循环变量的值。
for
循环适用于需要固定次数重复执行的情况,循环次数在循环开始前就已知。
while
循环:
while
循环是一种在未知循环次数的情况下使用的循环结构。它在每次循环迭代之前检查循环条件是否为真,只要条件为真,就会继续执行循环体内的代码块。while
循环适用于需要根据条件重复执行代码块的情况,循环次数在循环开始前不一定已知。
do-while
循环:
do-while
循环是一种与while
循环类似的循环结构,不同之处在于它会先执行循环体内的代码块,然后再检查循环条件是否为真。do-while
循环至少会执行一次循环体内的代码块,然后在每次循环迭代之前检查循环条件是否为真。do-while
循环适用于需要至少执行一次循环体的情况,循环次数在循环开始前不一定已知。总结:
for
循环适用于已知循环次数的情况。while
循环适用于根据条件循环执行代码块的情况。do-while
循环适用于至少执行一次循环体的情况。在实际使用中,根据不同的需求和场景,选择合适的循环结构可以提高代码的可读性和执行效率。
6、continue与break关键字
- continue:跳过某次循环内容,继续开始下一层循环,只能在循环中使用
- break:跳出整个循环,终止循环体内容的执行,只能在循环和switch中使用
- 标号:可以给语句块加标号赋予它们名称,标号位于语句之前。标号只能被continue和break引用。
public class Test{ public static void main(String[] args){ int n = 1; lo: //标号 while(true){ switch(n){ case 1: System.out.println("1"); break lo; //通过标号,这里的break将结束外层while循环 } } } }
语句前只允许加一个标号,标号后面不能跟大括号。通过用break后加标号对处于标号中的语句进行控制。往往标号后是for、while、do-while等循环
五、Java数组的定义和使用
数组(array):是一种容器,用来存储同种数据类型(或者比它所占字节小的)的多个值
语法:
//1.数据类型[] 变量名 【最常用】 int[] array; //2.数据类型 变量名[] int array[];
与C、C++不同,Java在定义数组时并不为数组元素分配内存,因此[ ]中无需指定数组元素的个数,即数组长度。而且对于如上定义的一个数组是不能访问它的任何元素的,我们必须要为它分配内存空间,这时要用到运算符new
在Java中,数组必须先初始化,才能使用
所谓初始化,就是在内存中,为数组容器开辟空间,并将数据存入容器的过程
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值
- 只明确元素个数,不明确具体数值时推荐使用
- 格式:
数据类型[] 变量名 = new 数据类型[数组长度];
- 范例:
int[] arr = new int[3];
- 注意:打印数组变量名,输出的是数组在内存中的地址值
静态初始化:初始化时就可以指定数组要存储的元素,系统还会自动计算出该数组的长度
- 需求中明确了具体数据,直接静态初始化即可
- 格式:
数据类型[] 变量名 = new 数据类型[]{数据1,数据2,数据3,....};
- 范例:
int[] arr = new int[]{1,2,3};
- 简化格式:
int[] arr = {1,2,3};
内存分配
Java程序在运行时,需要在内存中分配空间,为了提高效率,就对空间进行了不同区域的划分
每一片区域都有特定的处理数据的方式和内存管理方式
- 栈内存:方法运行时,进入的内存,局部变量都存放于这块内存当中
- 堆内存:new出来的内容(引用类型)就会进入堆内存,并且会存在地址值
- 方法区:字节码文件加载时进入的内存
- 本地方法栈:调用操作系统相关资源
- 寄存器:交给CPU去使用
你可以在声明数组的同时进行初始化(静态初始化),也可以在声明以后进行初始化(动态初始化)。例如:
// 静态初始化 // 静态初始化的同时就为数组元素分配空间并赋值 int intArray[] = {1,2,3,4}; String stringArray[] = {"微学苑", "http://www.weixueyuan.net", "一切编程语言都是纸老虎"}; // 动态初始化 float floatArray[] = new float[3]; floatArray[0] = 1.0f; floatArray[1] = 132.63f; floatArray[2] = 100F;
数组引用
可以通过下标来引用数组:
arrayName[index];
与C、C++不同,Java对数组元素要进行越界检查以保证安全性。
每个数组都有一个length属性来指明它的长度,例如 intArray.length 指明数组 intArray 的长度。
【示例】写一段代码,要求输入任意5个整数,输出它们的和。import java.util.*; public class Demo { public static void main(String[] args){ int intArray[] = new int[5]; long total = 0; int len = intArray.length; // 给数组元素赋值 System.out.print("请输入" + len + "个整数,以空格为分隔:"); Scanner sc = new Scanner(System.in); for(int i=0; i<len; i++){ intArray[i] = sc.nextInt(); } // 计算数组元素的和 for(int i=0; i<len; i++){ total += intArray[i]; } System.out.println("所有数组元素的和为:" + total); } }
数据常见操作
获取最值
- 定义一个变量,用于保存最大值(或最小值)
- 取数组中的第一个值作为变量的初始值(假设第一个值就是最大/小值)
- 与数组中的剩余数据逐个对比
int[] arr = {1, 2, 3, 4, 5, 6, 7000, 8, 919}; int max = arr[0]; for(int i = 0; i < arr.length; i++){ if(arr[i] > max) max = arr[i]; } System.out.println("最大值为:" + max);
数组元素求和
import java.util.Scanner; public class test{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int[] arr = new int[]; int sum = 0; for(int i = 0; i < arr.length; i++){ System.out.print("请输入第" + (i+1) + "个数值:"); int n = sc.nextInt(); sum += n; } System.out.println("数组内的元素的和为:" + sum); } }
数组基本查找
int[] arr = {19, 28, 37, 46, 50}; Scanner sc = new Scanner(System.in); System.out.print("请输入您要查找的数据:"); int n = sc.nextInt(); for(int i = 0; i < arr.length; i++){ if(arr[i] == n){ System.out.println("您要查找的数据索引为:" + i); break; } }
二维数组
二维数组的声明、初始化和引用与一维数组相似:
int intArray[ ][ ] = { {1,2}, {2,3}, {4,5} }; int a[ ][ ] = new int[2][3]; a[0][0] = 12; a[0][1] = 34; // ...... a[1][2] = 93;
Java语言中,由于把二维数组看作是数组的数组,数组空间不是连续分配的,所以不要求二维数组每一维的大小相同。例如:
int intArray[ ][ ] = { {1,2}, {2,3}, {3,4,5} }; int a[ ][ ] = new int[2][ ]; a[0] = new int[3]; a[1] = new int[5];
【示例】通过二维数组计算两个矩阵的乘积。
public class Demo { public static void main(String[] args){ // 第一个矩阵(动态初始化一个二维数组) int a[][] = new int[2][3]; // 第二个矩阵(静态初始化一个二维数组) int b[][] = { {1,5,2,8}, {5,9,10,-3}, {2,7,-5,-18} }; // 结果矩阵 int c[][] = new int[2][4]; // 初始化第一个矩阵 for(int i=0; i<2; i++) for(int j=0; j<3 ;j++) a[i][j] = (i+1) * (j+2); // 计算矩阵乘积 for (int i=0; i<2; i++){ for (int j=0; j<4; j++){ c[i][j]=0; for(int k=0; k<3; k++) c[i][j] += a[i][k] * b[k][j]; } } // 输出结算结果 for(int i=0; i<2; i++){ for (int j=0; j<4; j++) System.out.printf("%-5d", c[i][j]); System.out.println(); } } }
运行结果:
25 65 14 -65
50 130 28 -130几点说明:
- 上面讲的是静态数组。静态数组一旦被声明,它的容量就固定了,不容改变。所以在声明数组时,一定要考虑数组的最大容量,防止容量不够的现象。
- 如果想在运行程序时改变容量,就需要用到数组列表(ArrayList,也称动态数组)或向量(Vector)。
- 正是由于静态数组容量固定的缺点,实际开发中使用频率不高,被 ArrayList 或 Vector 代替,因为实际开发中经常需要向数组中添加或删除元素,而它的容量不好预估。
六、方法
方法就是一段具有独立功能 的代码块,不调用就不执行
基本使用
- 方法必须先创建才可以使用,该过程称为方法的定义
- 方法创建后并不是直接运行的,需要手动使用后才执行,该过程称为方法调用
语法
public void 方法名(){ //方法体 }
方法调用:
方法名();
注意
- 方法必须先定义后调用,否则程序将会报错
- 方法与方法之间是平级关系,不能嵌套定义
- 在方法没有被调用的时候,都在方法区中的字节码文件(.class)中存储
- 方法被调用的时候,需要进入到栈内存中运行
带参方法
形参和实参 形参:全称形式参数,是指方法定义中的参数 实参:全称实际参数,是指方法调用中的参数
语法
public void 方法名(参数){ //方法体 }
单个参数:
数据类型 变量名
多个参数:数据类型 变量名1 , 数据类型 变量名2 , .....
调用
方法名(变量名/常量值);
方法名(变量名1/常量值1 , 变量名2/常量值2 , ...);
方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将会报错
案例:
public class ParameterizedMethodExample { public static void main(String[] args) { int number1 = 10; int number2 = 5; // 调用带参方法,并传入两个整数作为参数 int sum = calculateSum(number1, number2); System.out.println("Sum: " + sum); } // 带参方法,用于计算两个整数的和 public static int calculateSum(int a, int b) { int sum = a + b; return sum; } }
带返回值方法
语法:
public 返回值数据类型 方法名(参数){ return 数据; }
- 方法定义时,return后面的返回值与方法定义上的数据类型要匹配,否则就会报错
- 在执行代码时,return语句后面的语句都不会执行,属于无效代码
return;
可以用于结束方法,也就是方法从栈内存中弹出去,该过程称为方法的弹栈当需要在方法内部执行一些操作并返回结果时,可以定义带有返回值的方法。下面是一个简单的示例,展示了Java中带返回值的方法的用法:
public class ReturnValueMethodExample { public static void main(String[] args) { int number1 = 10; int number2 = 5; // 调用带返回值的方法,并将返回结果赋值给变量 int maxNumber = findMax(number1, number2); System.out.println("Max Number: " + maxNumber); } // 带返回值的方法,用于找到两个整数的最大值,并返回结果 public static int findMax(int a, int b) { int max = (a > b) ? a : b; return max; } }
方法重载
方法名相同,参数也完全相同,称为方法的重复定义,是一种冲突性的错误 在调用方法的时候,Java虚拟机会通过参数的不同来区分同名的方法
- 在同一个类中,定义了多个同名的方法,但每个方法具有不同的参数类型或参数个数,这些同名的方法,就构成了重载关系
- 好处:不用记忆过多繁琐的方法名字
- 注意:识别方法之间是否是重载关系,只看方法名和参数,和返回值无关
方法重载(Method Overloading)是指在一个类中可以定义多个方法名称相同但参数列表不同的方法。下面是一个简单的示例,展示了Java中方法重载的用法:
public class MethodOverloadingExample { public static void main(String[] args) { int result1 = add(5, 10); double result2 = add(2.5, 3.7); int result3 = add(1, 2, 3); System.out.println("Result 1: " + result1); System.out.println("Result 2: " + result2); System.out.println("Result 3: " + result3); } // 方法重载示例 public static int add(int a, int b) { return a + b; } public static double add(double a, double b) { return a + b; } public static int add(int a, int b, int c) { return a + b + c; } }
方法的重写
方法重写(Method Overriding)是指在子类中重新定义(覆盖)从父类继承而来的方法,使得子类可以根据自身的需求来改变方法的实现。重写的方法具有相同的名称、参数列表和返回类型。
下面是一个简单的示例,展示了Java中方法重写的用法:
class Animal { public void makeSound() { System.out.println("动物发出声音"); } } class Cat extends Animal { @Override public void makeSound() { System.out.println("猫发出喵喵的声音"); } } public class MethodOverrideExample { public static void main(String[] args) { Animal animal = new Animal(); animal.makeSound(); // 输出: 动物发出声音 Cat cat = new Cat(); cat.makeSound(); // 输出: 猫发出喵喵的声音 } }
在上述示例中,有一个父类
Animal
和一个子类Cat
。父类Animal
有一个名为makeSound
的方法,子类Cat
通过使用@Override
注解重写了父类的makeSound
方法,并在方法体中改变了实现逻辑。在
main
方法中,创建了一个父类对象animal
和一个子类对象cat
,分别调用它们的makeSound
方法。由于方法重写的存在,调用子类对象的makeSound
方法时会执行子类中重写的方法实现,而不是父类中的方法实现。方法重写使得子类可以在继承的基础上修改和定制父类的行为,实现了多态性的一种表现。
七、String字符串
在Java中,
String
是一个类,用于表示字符串。它是Java中最常用的数据类型之一,用于存储和操作文本数据。String
类是不可变的,也就是说,一旦创建了一个字符串对象,它的值就不能被修改。
String
类提供了许多其他的方法,用于处理和操作字符串。由于String
是不可变的,每次对字符串的修改都会生成一个新的字符串对象。在处理大量字符串或频繁修改字符串内容时,建议使用StringBuilder
或StringBuffer
类,它们提供了可变的字符串操作的功能,可以提高性能。public class StringExample { public static void main(String[] args) { String str1 = "Hello"; String str2 = "World"; // 字符串拼接 String greeting = str1 + " " + str2; System.out.println("拼接结果:" + greeting); // 字符串长度 int length = greeting.length(); System.out.println("字符串长度:" + length); // 字符串比较 String str3 = "hello"; boolean isEqual = str1.equals(str3); System.out.println("字符串比较结果:" + isEqual); // 字符串查找 int index = greeting.indexOf("World"); System.out.println("查找结果:" + index); // 字符串提取 String subStr = greeting.substring(6); System.out.println("提取结果:" + subStr); // 字符串替换 String replacedStr = greeting.replace("Hello", "Hi"); System.out.println("替换结果:" + replacedStr); // 字符串转换 String upperCaseStr = greeting.toUpperCase(); System.out.println("大写转换结果:" + upperCaseStr); String lowerCaseStr = greeting.toLowerCase(); System.out.println("小写转换结果:" + lowerCaseStr); } }
在上述示例中,我们定义了两个字符串
str1
和str2
,然后进行了一系列的字符串操作:
- 使用
+
运算符进行字符串拼接,将str1
、空格和str2
连接起来。- 使用
length()
方法获取字符串的长度。- 使用
equals()
方法比较两个字符串是否相等。- 使用
indexOf()
方法查找子字符串在原字符串中的位置。- 使用
substring()
方法提取字符串的子串。- 使用
replace()
方法将字符串中的子串替换为新的字符串。- 使用
toUpperCase()
和toLowerCase()
方法将字符串转换为大写和小写形式。运行以上代码,将会输出以下结果:
拼接结果:Hello World 字符串长度:11 字符串比较结果:false 查找结果:6 提取结果:World 替换结果:Hi World 大写转换结果:HELLO WORLD 小写转换结果:hello world
这个例子演示了一些常见的String操作,你可以根据需要修改和扩展示例代码。String类提供了许多其他的方法,用于处理和操作字符串,你可以参考Java官方文档以获得更详细的了解。
StringBuffer与StringBuider
在Java中,
StringBuffer
和StringBuilder
是用于可变字符串操作的类。它们提供了类似于String
的功能,但与String
不同的是,它们的内容可以修改。以下是关于
StringBuffer
和StringBuilder
的特点和区别:
可变性:
StringBuffer
和StringBuilder
都是可变的,允许修改字符串内容。String
是不可变的,每次对字符串的修改都会创建一个新的字符串对象。线程安全性:
StringBuffer
是线程安全的,适用于多线程环境。StringBuilder
是非线程安全的,适用于单线程环境。性能:
StringBuilder
相对于StringBuffer
具有更好的性能,因为StringBuilder
不需要处理线程同步的开销。方法:
StringBuffer
和StringBuilder
提供了类似于String
的方法,例如length()
、charAt()
、indexOf()
等。- 除了这些方法,它们还提供了额外的方法用于字符串的插入、删除、替换和反转等操作。
使用示例:
public class StringBufferStringBuilderExample { public static void main(String[] args) { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("Hello"); stringBuffer.append(" "); stringBuffer.append("World"); String result1 = stringBuffer.toString(); System.out.println("StringBuffer Result: " + result1); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("Hello"); stringBuilder.append(" "); stringBuilder.append("World"); String result2 = stringBuilder.toString(); System.out.println("StringBuilder Result: " + result2); } }
在上述示例中,我们创建了一个
StringBuffer
对象和一个StringBuilder
对象,通过append()
方法将字符串连接起来。最后,使用toString()
方法将StringBuffer
和StringBuilder
对象转换为String
类型的结果,并输出到控制台。输出结果:
StringBuffer Result: Hello World StringBuilder Result: Hello World
StringBuffer
和StringBuilder
是在处理大量字符串操作时的有用工具,特别是当需要频繁修改字符串内容时。如果在单线程环境下操作字符串,建议使用StringBuilder
,它具有更好的性能。如果在多线程环境下操作字符串,应使用StringBuffer
以确保线程安全。
以上我们学习了java语言的介绍、第一个java程序、数据类型、数组等相关java基础知识,Java是一种广泛使用的面向对象编程语言,具有简单、可靠、安全和跨平台等特点,希望小伙伴们可以早日掌握java,成为一名优秀的java开发工程师