Skip to content

基础语法

你好,Java!写出第一行代码,从变量到方法,从原理到面试 🚀

🎯 场景:第一次运行 Java

┌─────────────────────────────────────────────────────────────────┐
│                      你好,Java 世界!                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   public class HelloWorld {                                     │
│       public static void main(String[] args) {                 │
│           System.out.println("Hello, World!");                  │
│       }                                                         │
│   }                                                             │
│                                                                  │
│   编译:javac HelloWorld.java → HelloWorld.class               │
│   运行:java HelloWorld → Hello, World!                        │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

这段代码告诉我们什么?

  • Java 是编译型语言,需要先编译后运行
  • main 方法是程序入口
  • System.out.println 是输出语句
  • 所有代码都要写在类里面(面向对象思想)

💡 实战场景:为什么 Java 能"一次编写,到处运行"?

  • 因为有 JVM!编译后的 .class 文件在任何装有 JVM 的机器上都能运行
  • 这就是 Java 的平台无关性!

变量与数据类型

基本数据类型

💡 实战场景:为什么需要不同的数据类型?

想象一下内存是停车场:

  • byte 就是小型车位,只能停自行车(-128 ~ 127)
  • int 是标准车位,大部分车都能停
  • long 是大型车位,大巴车才需要
  • float/double 是计时车位,精确到秒

用对数据类型,省空间又高效!

Java 有 8 种基本数据类型,分为四大类:

类别类型占用空间取值范围默认值面试点
整数byte1 字节-128 ~ 1270范围计算
整数short2 字节-32768 ~ 327670很少使用
整数int4 字节-2³¹ ~ 2³¹-10高频面试
整数long8 字节-2⁶³ ~ 2⁶³-10L金额计算用 BigDecimal
浮点float4 字节-3.4e38 ~ 3.4e380.0f精度问题
浮点double8 字节-1.7e308 ~ 1.7e3080.0d最常用
字符char2 字节0 ~ 65535'\u0000'Unicode
布尔boolean1 位true/falsefalse面试常问

💡 实战提示:金额计算不要用 float/double,用 BigDecimal

java
// ❌ 错误:浮点数精度问题
System.out.println(0.1 + 0.2); // 0.30000000000000004

// ✅ 正确:使用 BigDecimal
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b)); // 0.3

引用数据类型

java
// 字符串 - 面试高频考点
String s1 = "hello";           // 字面量,存在字符串常量池
String s2 = new String("hello"); // new 对象,堆中创建

// 数组
int[] arr = {1, 2, 3};
String[] names = new String[5];

// 类和接口
List<String> list = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();

💡 面试点:String 为什么不可变?字符串常量池了解吗?

java
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");

System.out.println(s1 == s2); // true - 指向常量池同一对象
System.out.println(s1 == s3); // false - 堆中新建对象
System.out.println(s1.equals(s3)); // true - 内容相同

运算符

算术运算符

💡 实战场景:点外卖时的价格计算

java
// 场景:购物车结算
double originalPrice = 99.9;      // 原价
int discount = 8;                 // 8折
double finalPrice = originalPrice * discount / 10; // 79.92

// 积分计算
int points = 1000;
int extraPoints = points % 100;  // 取余,够100积分的零头
java
int a = 10, b = 3;

System.out.println(a + b);  // 13
System.out.println(a - b);  // 7
System.out.println(a * b);  // 30
System.out.println(a / b);  // 3  (整数除法)
System.out.println(a % b);  // 1  (取余)
System.out.println(a++);     // 10 (先取值后加1)
System.out.println(++a);     // 12 (先加1后取值)

关系运算符

💡 实战场景:用户年龄验证

java
int age = 20;

// if 条件判断
if (age >= 18) {
    System.out.println("成年人");
} else {
    System.out.println("未成年");
}
java
System.out.println(5 > 3);   // true
System.out.println(5 == 5); // true
System.out.println(5 != 3); // true

逻辑运算符

💡 实战场景:登录校验

java
// 场景:用户登录条件判断
String username = "admin";
String password = "123456";
int failedAttempts = 3;

// && 短路与:用户名对 AND 密码对 AND 失败次数少于5
if (username.equals("admin") && password.equals("123456") && failedAttempts < 5) {
    System.out.println("登录成功!");
}
java
// && 和 & 的区别
int x = 5;
if (x > 3 && x++ > 0) { } // 短路与,x++不执行,x=5
if (x > 3 & x++ > 0) { }  // 非短路与,x++执行,x=6

// || 和 | 的区别同理

💡 面试点:&& 和 & 的区别?什么情况下不能用 &&?

位运算符

java
int a = 6; // 二进制: 110
int b = 3; // 二进制: 011

System.out.println(a & b);  // 2  (110 & 011 = 010)
System.out.println(a | b);  // 7  (110 | 011 = 111)
System.out.println(a ^ b);  // 5  (110 ^ 011 = 101)
System.out.println(~a);      // -7 (按位取反)
System.out.println(a << 1);  // 12 (左移1位,相当于乘2)
System.out.println(a >> 1);  // 3  (右移1位,相当于除2)

💡 实战应用:用位运算判断奇偶数,比 % 更高效

java
// ❌ 用 % 判断
if (n % 2 == 1) { ... }

// ✅ 用位运算判断 (n & 1) == 1
if ((n & 1) == 1) { ... } // 奇数

控制流程

条件语句

💡 实战场景:电商网站的优惠活动

java
// 场景:双十一优惠活动
double totalAmount = 888.0;

// 普通顾客
double discount = 0.9; // 9折
if (totalAmount >= 500) {
    discount = 0.8; // 满500打8折
}
if (totalAmount >= 1000) {
    discount = 0.7; // 满1000打7折
}

System.out.println("实付:" + totalAmount * discount);

if-else 简化写法(三元运算符)

java
// ❌ 啰嗦写法
int max;
if (a > b) {
    max = a;
} else {
    max = b;
}

// ✅ 简洁写法
int max = (a > b) ? a : b;

💡 面试点:三元运算符表达式1和表达式2类型不一致怎么办?

java
Object o = true ? new Integer(1) : new Double(2.0);
// 输出: 1.0 - 自动类型提升为 Double

switch 表达式(Java 14+)

java
// 传统 switch
switch (day) {
    case 1:
    case 2:
    case 3:
        System.out.println("工作日");
        break;
    case 4:
    case 5:
        System.out.println("工作日");
        break;
    default:
        System.out.println("周末");
}

// 新版 switch (Java 14+)
String result = switch (day) {
    case 1, 2, 3, 4, 5 -> "工作日";
    case 6, 7 -> "周末";
    default -> "无效日期";
};

循环语句

for 循环的几种形式

java
// 普通 for 循环
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// 增强 for 循环 (for-each) - 面试常问
int[] arr = {1, 2, 3, 4, 5};
for (int num : arr) {
    System.out.println(num);
}

// 带标签的循环 (break 外层)
outer:
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (i == 1 && j == 1) {
            break outer; // 跳出外层循环
        }
        System.out.println(i + "," + j);
    }
}

💡 面试点:for-each 和普通 for 循环的区别?什么时候不能用 for-each?

java
// ❌ for-each 无法修改数组元素
for (int num : arr) {
    num = num * 2; // 修改的是局部变量,不影响原数组
}

// ❌ for-each 无法获取索引
for (int num : arr) {
    System.out.println(num); // 不知道当前是第几个元素
}

// ✅ 需要修改元素或获取索引时,用普通 for
for (int i = 0; i < arr.length; i++) {
    arr[i] *= 2;
}

循环控制技巧

java
// 跳过当前迭代 (continue)
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        continue; // 跳过偶数
    }
    System.out.println(i); // 打印奇数
}

// 双重循环标志位
boolean found = false;
for (int i = 0; i < 100 && !found; i++) {
    for (int j = 0; j < 100; j++) {
        if (arr[i][j] == target) {
            found = true;
            break;
        }
    }
}

方法

方法定义与调用

💡 实战场景:计算电商订单总价

java
public class OrderCalculator {

    // 场景:计算订单总价(含折扣、优惠券)
    public double calculateTotal(double originalPrice, int quantity, double discount) {
        // 基础价格 * 数量 * 折扣
        return originalPrice * quantity * discount;
    }

    // 场景:判断是否包邮
    public boolean isFreeShipping(double totalPrice) {
        return totalPrice >= 99.0; // 满99包邮
    }

    // 可变参数方法 - 灵活计算多个商品总价
    public double sumPrices(double... prices) {
        double total = 0;
        for (double price : prices) {
            total += price;
        }
        return total;
    }
}
java
public class MethodDemo {

    // 无返回值方法
    public void printMessage(String msg) {
        System.out.println(msg);
    }

    // 有返回值方法
    public int add(int a, int b) {
        return a + b;
    }

    // 可变参数方法 (Java 5+)
    public int sum(int... numbers) {
        int total = 0;
        for (int num : numbers) {
            total += num;
        }
        return total;
    }

    // 方法重载 - 参数个数、类型或顺序不同
    public void print(int num) { }
    public void print(String str) { }
    public void print(int num, String str) { }
}

💡 面试点:方法重载和重写的区别?

区别重载 (Overload)重写 (Override)
发生位置同一个类父子类之间
方法名必须相同必须相同
参数列表必须不同必须相同
返回类型可以不同必须相同或子类型
访问修饰符可以不同不能更严格
抛出异常可以不同不能抛出新异常

值传递还是引用传递?

💡 面试高频题:Java 是值传递还是引用传递?

java
public class PassByValue {

    public void changePrimitive(int num) {
        num = 100; // 只改变局部变量
    }

    public void changeString(String str) {
        str = "changed"; // 局部变量指向新对象
    }

    public void changeArray(int[] arr) {
        arr[0] = 100; // 改变了原数组内容
        arr = new int[]{999}; // 局部变量指向新数组
    }

    public static void main(String[] args) {
        PassByValue demo = new PassByValue();

        int num = 10;
        demo.changePrimitive(num);
        System.out.println(num); // 10 - 原值不变

        String str = "original";
        demo.changeString(str);
        System.out.println(str); // original - 原值不变

        int[] arr = {1, 2, 3};
        demo.changeArray(arr);
        System.out.println(arr[0]); // 100 - 数组内容被修改
    }
}

结论:Java 永远是值传递。引用类型传递的是引用的副本(地址值)。


数组

数组声明与初始化

java
// 声明方式
int[] arr1;        // 推荐写法
int arr2[];        // C 风格,不推荐

// 初始化方式
int[] arr1 = new int[5];         // 默认值 0
int[] arr2 = new int[]{1, 2, 3}; // 指定初始值
int[] arr3 = {1, 2, 3, 4, 5};    // 简写(静态初始化)

String[] names = {"Alice", "Bob", "Carol"};

数组常用操作

java
int[] arr = {64, 25, 12, 22, 11};

// 获取长度
int length = arr.length; // 5

// 遍历数组
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

// 查找元素 (线性查找)
int find = 22;
int index = -1;
for (int i = 0; i < arr.length; i++) {
    if (arr[i] == find) {
        index = i;
        break;
    }
}

// 排序 (Arrays 工具类)
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // [11, 12, 22, 25, 64]

// 二分查找 (前提:已排序)
int index = Arrays.binarySearch(arr, 22); // 2

二维数组

java
// 定义方式
int[][] matrix = new int[3][4];     // 3行4列
int[][] arr = {{1,2}, {3,4}, {5,6}}; // 静态初始化

// 遍历
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

关键字总结

static 关键字

💡 面试高频点:static 关键字的作用?

java
public class StaticDemo {

    // 1. 静态变量 - 所有对象共享
    private static int count = 0;

    // 2. 静态方法 - 可直接通过类名调用
    public static int getCount() {
        return count;
    }

    // 3. 静态代码块 - 类加载时执行一次
    static {
        System.out.println("类加载时执行");
        // 初始化静态资源
    }

    // 4. 静态内部类
    public static class Inner {
        public void show() {
            System.out.println("静态内部类方法");
        }
    }
}

// 调用方式
int count = StaticDemo.getCount(); // 无需创建对象
StaticDemo.Inner inner = new StaticDemo.Inner();

static 内存图解

┌─────────────────────────────────────────┐
│                  堆内存                   │
│  ┌─────────────────────────────────┐   │
│  │         对象1 (count=1)          │   │
│  └─────────────────────────────────┘   │
│  ┌─────────────────────────────────┐   │
│  │         对象2 (count=2)          │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│               方法区 (Method Area)       │
│  ┌─────────────────────────────────┐   │
│  │  static count = 2 (共享)         │   │
│  │  static getCount()              │   │
│  │  static {} 代码块               │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘

final 关键字

java
// 1. final 变量 - 常量,赋值后不能改变
final int NUM = 100;
// NUM = 200; // 编译错误

// 2. final 方法 - 不能被重写
public final void method() { }

// 3. final 类 - 不能被继承
public final class String { }

// 4. final 参数 - 方法内不能修改
public void test(final int num) {
    // num = 100; // 编译错误
}

// 面试点:final 修饰 String 有什么效果?
// String 被 final 修饰,不能被继承,保证安全性

总结

基础语法核心知识点

知识点面试频率实战重要性
基本数据类型⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
运算符⭐⭐⭐⭐⭐⭐⭐⭐
控制流程⭐⭐⭐⭐⭐⭐⭐⭐
方法参数传递⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
数组⭐⭐⭐⭐⭐⭐⭐⭐
static 关键字⭐⭐⭐⭐⭐⭐⭐⭐⭐
final 关键字⭐⭐⭐⭐⭐⭐⭐⭐⭐

⚠️ 易错点提醒

  1. 浮点数比较不用 ==,用 BigDecimal
  2. switch 支持 String (Java 7+)
  3. for-each 不能修改元素和获取索引
  4. Java 永远是值传递
  5. String 是不可变对象