java学习 - 02 从C语言到java的过渡

一. 运算符

1. 概念

计算机的最基本的用途之一就是执行数学运算,比如:

int a = 3;
int b = 4;
a + b;
a < b;

上述的+<就是运算符,即:对操作数进行操作时的符号,不同运算符操作的含义不同。

作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量。Java中运算符可分为以下几类:

  • 算术运算符(+ - * / %)
  • 关系运算符(< > == != <= >=)
  • 逻辑运算符(&& || !)
  • 位运算符(& | ~ ^)
  • 移位运算符(<< >> >>>)等

2. 算术运算符

  • int / int 结果还是int类型,而且会向下取整
  • 做除法和取模时,右操作数不能为0
  • % 不仅可以对整型取模,也可以对double类型取模,但是没有意义,一般都是对整型取模的
  • 两侧操作数类型不一致时,向类型大的提升
System.out.println(1 + 2.0); //+的左侧是int,右侧是double,在加之前int被提升为double
                              //故:输出3.0

3. 关系运算符

关系运算符的计算结果是true或false

int a = 3;
int b = 4;
System.out.println(a < b);   //true
System.out.println(a == b);  //false

4. 逻辑运算符

  • 逻辑运算符的运算结果都是boolean类型
  • 表达式必须是boolean类型的结果
  • 短路求值:
    • && 和 || 遵守短路求值的规则
    • 对于 && , 如果左侧表达式值为 false, 则表达式结果一定是 false, 无需计算右侧表达式
    • 对于 ||, 如果左侧表达式值为 true, 则表达式结果一定是 true, 无需计算右侧表达式
  • & 和 | 如果表达式结果为 boolean 时, 也表示逻辑运算。但与 && || 相比, 它们不支持短路求值
System.out.println(3 > 4 && 3 / 0 == 0);    //打印false
System.out.println(3 < 4 || 3 / 0 == 0);    //打印true
System.out.println(3 > 4 & 3 / 0 == 0);     //程序抛出异常
System.out.println(3 < 4 | 3 / 0 == 0);     //程序抛出异常

5. 位运算符

  • 按位与 &,boolean isOdd = (num & 1) == 1,可用于判断奇偶
System.out.println(3 & 4); //0011 & 0100 = 0000
  • 按位或 |
System.out.println(3 | 4); //0011 | 0100 = 0111
  • 按位取反 ~
System.out.println(~3); //~00000000000000000000000000000011
                        //11111111111111111111111111111100是-4的补码
  • 按位异或 ^
System.out.println(3 ^ 4); //0011 ^ 0100 = 0111

6. 移位运算

  • 左移<<:相当于乘2,最右侧补0
System.out.println(3 << 1); //6
  • 右移>>:相当于除2,最右侧去掉,最左侧补符号位(正数补0,负数补1)
System.out.println(3 >> 1); //1
  • 无符号右移 >>>: 最右侧位不要了, 最左侧补 0
System.out.println(-3 >>> 1); //2147483646

高效的乘除运算:

7. 与C语言相比

  • 指针运算符:
    • C语言支持指针运算符(* 和 &),可以直接操作内存地址
    • Java不支持指针,提供了更高层次的内存管理和安全性
  • 位运算符:
    • 两者都支持基本的位运算符(如 &, |, ^, ~)
    • Java增加了无符号右移运算符 >>>,而C语言没有
  • 字符串连接:
    • Java使用 + 运算符进行字符串连接
    • C语言没有直接的字符串连接运算符,通常使用 strcat 函数
  • 布尔运算符:
    • Java中的布尔类型是 boolean,只能是 true 或 false
    • C语言中没有布尔类型,通常使用整数来表示布尔值(0 为假,非0 为真)

二. 逻辑控制

1. if语句

语法格式:

if(布尔表达式1){ 
  // 语句1 
} else if(布尔表达式2){
  // 语句2 
} else {
  // 语句3 
}

2. switch语句

switch(表达式){
  case 常量值1:{ 
    语句1;
    break;
  }
  case 常量值2:{
    语句2; 
    break;
  }
  default:{ 
    内容都不满足时执行语句; 
    break;
  }
}

3. 循环

while循环

while(循环条件){ 
  循环语句; 
}

do while 循环:

do{ 
  循环语句; 
}while(循环条件); //注意分号

for循环:

for(表达式①;布尔表达式②;表达式③){
  表达式④; 
}
  • 表达式1: 用于初始化循环变量初始值设置,在循环最开始时执行,且只执行一次
  • 表达式2: 循环条件,满则循环继续,否则循环结束
  • 表达式3: 循环变量更新方式

4. 输出到控制台

格式化字符串

c507be42ce5a4b198c133a67c75a41d6.png

5. 从键盘输入

使用 Scanner 读取字符串/整数/浮点数:

public static void main(String[] args){
  Scanner scanner = new Scanner(System.in);
  
  //使用Scanner读取字符串/整数/浮点数
  System.out.println("接收数值");
  int num = scanner.nextInt();
  System.out.println(num);
  
  System.out.println("循环接收数值");
  while(scanner.hasNext()){
    int num1 = scanner.nextInt();
    System.out.println(num1);
  }
  System.out.println("Ctrl+d结束接收");
  
  scanner.close();//在使用完Scanner后关闭它
  //(使用scanner.close()),以避免资源泄漏。
}

6. 与C语言相比

  1. switch语句:

    • Java的switch语句支持String类型,而C语言只支持整数类型(如int和char)
    • 从Java14开始,switch可以用作表达式,返回一个值
  2. for-each循环:

    • Java提供了增强型for循环(for-each),用于遍历数组和集合
    • C语言没有直接的for-each循环,需要使用普通for循环或指针来遍历数组
  3. 异常处理:

    • Java有内置的异常处理机制(try-catch-finally),用于处理错误和异常
    • C语言依赖于函数返回值和错误码来处理错误,没有内置的异常处理机制
  4. 布尔控制结构:

    • Java中的条件语句(如if和while)要求条件表达式必须是boolean类型
    • C语言允许整数作为条件表达式,0为假,非0为真
  5. 类型安全:

    • Java通过Scanner类提供了更高的类型安全性和异常处理
    • C语言的scanf需要小心处理格式字符串,以避免缓冲区溢出等问题
  6. 输入方式:

    • Java的Scanner支持多种数据类型和输入源
    • C语言的scanf需要格式化字符串来指定输入类型

三. 方法的使用

1. 概念

方法就是一个代码片段,类似于C语言中的"函数"。方法存在的意义:

  • 代码重用:方法允许将常用的代码封装起来,以便在需要时重复使用,减少代码重复
  • 模块化:方法将程序分解为更小的、可管理的部分,使代码更易于理解和维护
  • 抽象:方法提供了实现细节的抽象,调用者不需要知道方法内部的实现,只需了解如何调用它
  • 信息隐藏:通过使用访问修饰符(如private、public),方法可以控制对类内部实现的访问,增强封装性

2. 定义

语法格式:

修饰符 返回值类型 方法名称([参数类型 形参 ...]){
  方法体代码;
  [return 返回值];
}

例如:

public static int add(int a , int b) {
  return a + b;
}

3. 方法执行的过程

调用方法 -> 参数传递 -> 栈帧创建 -> 控制权转移 -> 代码执行 -> 局部变量处理 -> 返回值处理 -> 栈帧销毁 -> 控制权返回 -> 回到主调方法继续往下执行

4. 方法的重载

  • 方法名必须相同
  • 参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
  • 与返回值类型是否相同无关
public static int add(int a, int b){
  return a + b;
}

public static double add(double a, double b){
  return a + b;
}

public static long add(long a, long b){
  return a + b;
}

5. 方法签名

   在同一个作用域中不能定义两个相同名称的标识符。比如:方法中不能定义两个名字一样的变量,那为什么类中就可以定义方法名相同的方法呢?

   方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。

6. 与C语言相比

  1. 定义与声明:

    • Java:方法必须在类中定义。方法的签名包括访问修饰符(如 public、private)、返回类型、方法名和参数列表
    • C:函数可以在任何地方定义,不需要类。函数原型可以在头文件中声明
  2. 访问修饰符:

    • Java:提供了多种访问修饰符(public、protected、private、默认包级别)来控制方法的可见性
    • C:没有访问修饰符。函数的可见性通常通过文件作用域控制(static关键字可以限制函数在文件内的可见性)
  3. 返回类型:

    • Java:所有方法必须声明返回类型,如果没有返回值则使用 void
    • C:类似地,函数必须声明返回类型,使用 void 表示无返回值
  4. 参数传递:

    • Java:参数传递的确是按值传递的,但对于对象来说,传递的是对象的引用的副本。这意味着方法内部可以修改对象的内容,但不能改变引用本身指向的对象(只有按值传递)
    • C:所有参数都是按值传递的。如果想要函数修改外部变量的值,通常通过传递指针来实现。指针可以直接访问和修改变量的内存地址
  5. 方法重载:

    • Java:支持方法重载,可以在同一个类中定义多个同名方法,只要参数列表不同
    • C:不支持函数重载。每个函数必须有唯一的名称
  6. 内存管理:

    • Java:有垃圾回收机制,自动管理内存
    • C:需要手动管理内存,使用 malloc 和 free 等函数
  7. 异常处理:

    • Java:提供了结构化的异常处理机制(try-catch-finally)
    • C:没有内置的异常处理机制,通常通过返回值或 setjmp/longjmp 实现错误处理

四. 数组的定义和使用

1. 数组的创建及初始化

Java中的数组是对象,它们存储在堆内存中。当你创建一个数组时,Java会在堆中分配一块连续的内存空间来存储数组元素。数组变量本身是一个引用,指向这块内存空间。

//动态初始化,数组的内容是在运行时可以逐步填充或改变
//(尽管大小固定),只是在声明时不需要提供具体的元素。
int[] array1 = new int[4];
//未赋值,默认为0

//静态初始化,因为数组的内容在声明时就已经完全确定和初始化。
int[] array2 = {1, 2, 3, 4}; //相当于下面的精简版
double[] array3 = new double[]{1.0, 2.0, 3.0, 4.0};

//空引用
int[] arr = null;

注意:null 的作用类似于 C 语言中的 NULL (空指针), 都是表示一个无效的内存位置。因此不能对这个内存进行任何读写操作。一旦尝试读写,就会抛出 NullPointerException。

如果没有对数组进行初始化,数组中元素有其默认值,如果数组中存储元素类型为基本类型,默认值为基本类型对应的默认值。

a4fb9ae16333470a95185e39b2917821.png

2. 遍历数组

for(int i = 0; i < array2.length; i++){
  System.out.print(array2[i] + " ");
}
System.out.println();

//foreach
for(int i : array2){
  System.out.print(i + " ");
}

3. 基本类型变量与引用类型变量的区别

  • 基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;
  • 而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。

  引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象。有点类似C语言中的指针,但是Java中引用要比指针的操作更简单。

4. 数组练习

数组转字符串:

String array = Arrays.toString(array2);
System.out.println(array);
[1, 2, 3, 4]

数组拷贝:

int[] array = {1, 2, 3, 4};
//1
int[] newArr = array;
newArr[0] = 5;
System.out.println("newArr:" + Arrays.toString(newArr));
//2
int[] newArr = Arrays.copyOf(array, array.length);
newArr[0] = 5;
System.out.println("newArr:" + Arrays.toString(newArr));
//3
int[] newArr = Arrays.copyOfRange(array, 0, array.length);
newArr[0] = 5;
System.out.println("newArr:" + Arrays.toString(newArr));
//4
public static int[] copyOf(int[] arr){
  int[] ret = new int[arr.length];
  for(int i = 0; i < arr.length; i++){
    ret[i] = arr[i];
  }
  return ret;
}

注意: 在Java中,在处理数组切片或子列表时,范围通常是左闭右开的,有助于避免越界错误。

二分查找:

int[] array = {1, 2, 3, 4};
int num = Arrays.binarySearch(array, 3);
System.out.println(num);

填充:

int[] array = {1, 2, 3, 4};
Arrays.fill(array, 0);
System.out.println(Arrays.toString(array));

将数组的值全置为0

5. 二维数组

不规则数组:

java

int[][] arr = new int[3][];
arr[0] = new int[9];
arr[1] = new int[4];
arr[2] = new int[5];

6. 与C语言相比

  1. 类型安全:

    • Java:数组是类型安全的,数组的类型在声明时就固定,不能存储其他类型的元素
    • C:数组不具备类型安全,可以通过指针操作存储不同类型的数据
  2. 边界检查:

    • Java:在访问数组时会进行边界检查,如果访问越界,会抛出 ArrayIndexOutOfBoundsException
    • C:不会进行边界检查,越界访问可能导致未定义行为或内存泄漏
  3. 数组大小:

    • Java:数组大小在创建时固定,不能动态改变
    • C:数组大小在声明时固定,但可以通过动态内存分配(如 malloc)创建可变大小的数组
  4. 内存管理:

    • Java:由垃圾回收器自动管理内存,不需要手动释放
    • C:需要手动管理内存,使用 malloc 和 free 分配和释放内存
  5. 多维数组:

    • Java:多维数组实际上是数组的数组,每一维可以有不同的长度
    • C:多维数组是连续的内存块,所有维度的大小必须在声明时指定
  6. 初始化:

    • Java:数组在创建时会自动初始化为默认值(如 int 类型的数组初始化为 0)
    • C:数组在声明时未自动初始化,包含垃圾值,除非显式初始化

        通过本文,我们全面回顾了Java编程语言的一些基础概念,包括运算符、逻辑控制、方法和数组。这些知识点是构建Java程序的基石,掌握它们对于成为一名优秀的Java开发者至关重要。

        我们探讨了Java与C语言的一些关键区别,这不仅有助于理解Java的特性,也能帮助有C语言背景的程序员更快地适应Java编程。Java的面向对象特性、自动内存管理和丰富的标准库,使其在开发大型、复杂的应用程序时具有显著优势。

        同时,我们还深入讨论了一些常见的数组操作算法。这些算法不仅在面试中经常被问到,在实际编程中也有广泛的应用。掌握这些算法能够帮助你写出更高效、更优雅的代码。

        需要注意的是,本文涵盖的内容仅是Java编程的冰山一角。Java是一门深度和广度都很大的语言,还有很多高级特性和复杂概念等待你去探索。

        学习编程是一个持续的过程,需要不断的实践和积累。希望这篇文章能为你的Java学习之旅提供一个良好的开端或复习的参考。记住,编程的真正乐趣在于用你所学的知识去解决实际问题,创造有价值的应用。

        最后,欢迎在评论区留下你的想法、问题或建议。如果你觉得这篇文章对你有帮助,也请别忘了点赞和收藏。让我们一起在Java的世界中不断学习、成长!

        祝你编程愉快,代码无bug!

 

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值