java基础

9 阅读14分钟

基础语法

基本数据类型

基本数据类型是 Java 内置的、最简单的数据存储形式,直接存储在栈内存中。

数据类型大小默认值取值范围说明
byte1字节0-128 ~ 127最小整数类型
short2字节0-32,768 ~ 32,767短整数
int4字节0-2³¹ ~ 2³¹-1 (-21亿~21亿)最常用的整数类型
long8字节0L-2⁶³ ~ 2⁶³-1长整数(需加 L/l 后缀)
float4字节0.0f单精度浮点数需加 F/f 后缀
double8字节0.0d双精度浮点数默认的浮点数类型
char2字节'\u0000'0 ~ 65,535Unicode 字符
boolean1位falsetrue / false布尔值(大小无明确定义)
@Test
void test() {
    // 整数类型
    int i = 100000;         // 最常用
    long l = 10000000000L;  // 需要加 L 后缀

    // 浮点类型
    float f = 3.14f;        // 需要加 f 后缀
    double d = 3.1415926;   // 默认双精度

    // 字符类型
    char c1 = 'A';          // 单引号
    char c2 = '\u0041';     // Unicode 编码(也是 'A')
    char c3 = 65;           // ASCII 码值

    // 布尔类型
    boolean flag = true;
}
引用数据类型

引用数据类型存储的是对象的引用(地址) ,实际对象存储在堆内存中。

  • 主要引用类型:
类型说明示例
类(Class)自定义的类StringPersonArrayList
接口(Interface)抽象的行为规范ListRunnableComparable
数组(Array)同一类型数据的集合int[]String[]
枚举(Enum)有限的常量集合enum Color { RED, GREEN, BLUE }
注解(Annotation)元数据标记@Override@Deprecated
 // 1. 类类型
        Person person = new Person("张三", 25);  // person 是引用
        String str = "Hello";                     // String 是类
        
        // 2. 数组类型
        int[] numbers = {1, 2, 3, 4, 5};         // 数组是对象
        String[] names = new String[3];          // 创建数组  长度为3
        
        // 3. 接口类型
        List<String> list = new ArrayList<>();   // 接口引用指向实现类
        
        // 4. null 值
        Person p = null;                         // 引用可以为 null
        // p.getName();                          // NullPointerException!
        
        // 5. 多重引用
        Person p1 = new Person("李四", 30);
        Person p2 = p1;                          // p1 和 p2 指向同一对象
        p2.setAge(31);                           // 会影响 p1 的对象
        
        System.out.println("p1 age: " + p1.getAge());  // 输出: 31
  • 引用类型的特点:
public class ReferenceDemo {
    public static void main(String[] args) {
        // == 比较的是引用地址
        String s1 = "Java";
        String s2 = "Java";
        String s3 = new String("Java");
        
        System.out.println(s1 == s2);      // true(字符串常量池)
        System.out.println(s1 == s3);      // false(不同对象)
        System.out.println(s1.equals(s3)); // true(内容相同)
        
        // 数组也是引用类型
        int[] arr1 = {1, 2, 3};
        int[] arr2 = {1, 2, 3};
        int[] arr3 = arr1;
        
        System.out.println(arr1 == arr2);  // false
        System.out.println(arr1 == arr3);  // true
        System.out.println(Arrays.equals(arr1, arr2));  // true(比较内容)
        
        // 参数传递:基本类型传值,引用类型传引用
        int num = 10;
        modifyValue(num);
        System.out.println("After modifyValue: " + num);  // 10(不变)
        
        int[] array = {1, 2, 3};
        modifyArray(array);
        System.out.println("After modifyArray: " + array[0]);  // 100(改变!)
    }
    
    static void modifyValue(int x) {
        x = 100;  // 不影响原始值
    }
    
    static void modifyArray(int[] arr) {
        arr[0] = 100;  // 修改会影响原始数组
    }
}
  • 基本类型 vs 引用类型
特性基本数据类型引用数据类型
存储位置栈内存堆内存(对象),栈内存(引用)
存储内容实际值对象的引用(地址)
默认值有(如 int=0)null
内存占用固定(根据类型)不固定(对象大小)
比较方式== 比较值== 比较引用地址,equals()比较内容
参数传递传值(不影响原变量)传引用(影响原对象)
GC 管理不需要由垃圾回收器管理
// 整型数组 默认初始化值是0
int[] arr = new int[5];
log.info("arr:{}", arr[0]); // 0

//引用类型数组  默认初始化值是null (空)
String[] arr1 = new String[5];
log.info("arr1:{}", arr1[0]); // null
== 和 equals()
  • 核心区别
比较项== 运算符equals() 方法
类型Java运算符Object类的方法
比较内容比较两个对象的内存地址比较两个对象的内容是否相等
适用范围基本类型和引用类型只能用于引用类型
默认实现无(语言特性)Object类中的实现就是==
可重写性不能重写可以被子类重写, 若不重写,比较的也是地址。
// 基本数据类型比较 - 比较值
int a = 10;
int b = 10;
System.out.println("int == int: " + (a == b));  // true

// 示例1:比较引用地址
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println("s1 == s2: " + (s1 == s2));  // false - 不同对象

// 示例2:指向同一个对象
String s3 = "World";
String s4 = s3;
System.out.println("s3 == s4: " + (s3 == s4));  // true - 同一个对象

// 示例3:字符串常量池
String s5 = "Java";
String s6 = "Java";
System.out.println("s5 == s6: " + (s5 == s6));  // true - 常量池中同一个对象
  • equals() 方法详解
// Object类中的equals方法源码
public class Object {
    public boolean equals(Object obj) {
        return (this == obj);  // 默认实现就是比较地址
    }
}
  • String类的重写实现equals方法,使得String类 equals 比较时只比较内容。
// String类的equals比较
String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = "Hello";
String str4 = "World";

System.out.println("str1.equals(str2): " + str1.equals(str2));  // true
System.out.println("str1.equals(str3): " + str1.equals(str3));  // true
System.out.println("str1.equals(str4): " + str1.equals(str4));  // false

// Integer类的equals比较
Integer num1 = new Integer(100);
Integer num2 = new Integer(100);
Integer num3 = 100;  // 自动装箱

System.out.println("\nInteger比较:");
System.out.println("num1 == num2: " + (num1 == num2));      // false
System.out.println("num1.equals(num2): " + num1.equals(num2));  // true
System.out.println("num2.equals(num3): " + num2.equals(num3));  // true
  • 包装类一般都重写equals方法,若不重写,调用Object类中的equals方法,就是在比较地址。但是我们希望内容相同的类应该是相等的
// 不重写equals()的问题
class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class WithoutOverrideEquals {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 20);
        Person p2 = new Person("张三", 20);
        
        System.out.println("p1 == p2: " + (p1 == p2));          // false
        System.out.println("p1.equals(p2): " + p1.equals(p2));  // false(使用Object的equals)
        
        // 我们希望内容相同的Person应该是相等的!
    }
}
基础语法
  • if-else 语句 [同js]
// if-else if-else语句
int year = 2024;
if (year % 4 == 0) {
    if (year % 100 != 0 || year % 400 == 0) {
        System.out.println(year + "年是闰年");
    } else {
        System.out.println(year + "年不是闰年");
    }
} else {
    System.out.println(year + "年不是闰年");
}

// 简化写法(三元运算符)
int a = 10, b = 20;
int max = (a > b) ? a : b;
System.out.println("最大值: " + max);

// 多个条件判断
boolean hasTicket = true;
boolean hasID = true;
int personAge = 16;

if (hasTicket && hasID && personAge >= 18) {
    System.out.println("可以进入");
} else {
    System.out.println("不符合进入条件");
}
  • switch 语句[同js]
  • 循环语句 for循环 while循环。 多层循环跳出:使用标签break/continue[同js]
// 标准for循环
for (int i = 0; i < 5; i++) {
    System.out.println("i = " + i);
}
   
// List遍历
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");
System.out.println("List遍历:");
// 方式1:传统for循环
for (int i = 0; i < list.size(); i++) {
    System.out.println("索引" + i + ": " + list.get(i));
}

// 方式2:增强for循环
System.out.print("增强for循环: ");
for (String item : list) {
    System.out.print(item + " ");
}
System.out.println();

// 方式3:迭代器
System.out.print("迭代器遍历: ");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.print(iterator.next() + " ");
}
System.out.println();

// 方式4:forEach(Java 8+)
System.out.print("forEach方法: ");
list.forEach(item -> System.out.print(item + " "));
System.out.println();


// Set遍历
Set<Integer> set = new HashSet<>();
set.add(10);
set.add(20);
set.add(30);
set.add(10);  // 重复元素不会被添加

System.out.println("\nSet遍历(无序):");
for (Integer num : set) {
    System.out.print(num + " ");
}
System.out.println();

// Map遍历
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 28);

System.out.println("\nMap遍历:");
// 方式1:遍历EntrySet
System.out.println("遍历EntrySet:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}

// 方式2:遍历KeySet
System.out.println("\n遍历KeySet:");
for (String key : map.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}

// 方式3:遍历Values
System.out.println("\n遍历Values:");
for (Integer value : map.values()) {
    System.out.print(value + " ");
}
System.out.println();

// 方式4:forEach(Java 8+)
System.out.println("\nforEach遍历:");
map.forEach((key, value) -> 
    System.out.println(key + " -> " + value));

包装类

基本类型包装类示例
intIntegerInteger i = 100;
longLongLong l = 100L;
floatFloatFloat f = 3.14f;
doubleDoubleDouble d = 3.14;
booleanBooleanBoolean flag = true;
自动装箱/拆箱
// 自动装箱:基本类型 → 包装类
Integer i1 = 100;           // 相当于 Integer.valueOf(100)
Double d1 = 3.14;           // 相当于 Double.valueOf(3.14)

// 自动拆箱:包装类 → 基本类型
int num = i1;               // 相当于 i1.intValue()
double value = d1;          // 相当于 d1.doubleValue()
log.info("num:{}, value:{}", num, value);

// 手动转换
Integer i2 = 200;
int intValue = i2.intValue();
log.info("intValue:{}", intValue);


// 字符串转换
String str = "123";
int numFromStr = Integer.parseInt(str);      // 返回 int
Integer integerFromStr = Integer.valueOf(str); // 返回 Integer
log.info("numFromStr:{}, integerFromStr:{}", numFromStr, integerFromStr);


// 注意:比较包装类对象
Integer a = 127;
Integer b = 127;
System.out.println(a == b);                  // true(缓存范围)

Integer c = 128;
Integer d = 128;
System.out.println(c == d);                  // false(超出缓存)
System.out.println(c.equals(d));             // true

Java 类

类的完整结构:
[修饰符] class 类名 {
    // 1. 属性(成员变量)
    [修饰符] 数据类型 属性名 [= 初始值];
    
    // 2. 方法(成员方法)
    [修饰符] 返回值类型 方法名(参数列表) {
        // 方法体
    }
    
    // 3. 构造器(构造方法)
    [修饰符] 类名(参数列表) {
        // 初始化代码
    }
    
    // 4. 代码块
    {
        // 实例代码块
    }
    
    static {
        // 静态代码块
    }
    
    // 5. 内部类
    [修饰符] class 内部类名 {
        // 内部类内容
    }
}
属性(成员变量)
  1. 定义类的状态或特征
  2. 有默认值(基本类型有默认值,引用类型为null)
public class Person {
    // 1. 实例变量 - 每个对象独立拥有
    private String name;        // 私有属性
    protected int age;          // 受保护属性
    public String gender;       // 公共属性
    
    // 2. 类变量(静态变量) - 类所有对象共享
    public static String species = "Human";
    
    // 3. 常量
    public static final double PI = 3.14159;
    private final String ID;    // 实例常量
    
    // 4. 初始化方式
    private int score = 100;    // 直接初始化
    private Date birthday = new Date();  // 对象初始化
   
}
方法(成员方法)
  1. 定义对象的行为或功能
  2. 可以重载(overload)
  3. 可以重写(override,继承时)
  • 重载(Overloading) vs 重写(Overriding)详解
特性重载(Overloading)重写(Overriding)
定义同一个类中,方法名相同,参数列表不同子类重新定义父类中已有的方法
位置同一个类中子类中
方法签名必须不同(参数类型、个数、顺序)必须相同
返回值可以不同必须兼容(相同或是协变)
访问权限可以不同不能更严格(可以更宽松)
异常可以不同不能抛出更宽泛的检查异常
静态性可以是静态或非静态不能是静态(必须是实例方法)
绑定编译时绑定(静态绑定)运行时绑定(动态绑定)
目的增加方法的功能性修改或扩展父类行为
关键词无特殊关键词@Override 注解(可选但推荐)
  • 重载
public class Calculator {

    // 重载示例1:参数个数不同
    public int add(int a, int b) {
        return a + b;
    }
    public int add(int a, int b, int c) {
        return a + b + c;
    }
    // 重载示例2:参数类型不同
    public double add(double a, double b) {
        return a + b;
    }

    // 重载示例3:参数顺序不同
    public void printInfo(String name, int age) {
        System.out.println("姓名: " + name + ", 年龄: " + age);
    }
    public void printInfo(int age, String name) {
        System.out.println("年龄: " + age + ", 姓名: " + name);
    }
}
  • 构造器重载
public class Person {
    private String name;
    private int age;
    private String address;
    
    // 无参构造器
    public Person() {
        this.name = "Unknown";
        this.age = 0;
    }
    
    // 一个参数构造器
    public Person(String name) {
        this.name = name;
        this.age = 0;
    }
    
    // 两个参数构造器
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 全参数构造器
    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
}

面向对象三大特征

封装性

封装是把对象的属性行为包装在一起,并对外隐藏实现细节,只暴露必要的接口。

  • 使用 private 修饰属性, 内部实现对外不可见
  • 提供 public 的 getter/setter 方法,通过方法访问和修改数据
继承性

继承是从已有的类派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

  • 使用 extends 关键字, 子类复用父类的代码,子类可以添加新的属性和方法
  • 单继承(Java只支持单继承)
  • 使用 super 调用父类成员
多态性

多态是指同一个行为具有多个不同表现形式的能力。同一个接口,使用不同的实例而执行不同操作。

  • 父类引用指向子类对象
  • 继承 + 方法重写
  • 接口实现
  • 执行机制:编译时看父类,运行时看子类。
// 编译时:编译器只认声明类型(父类/接口)
Animal animal = new Dog();  // Animal是声明类型,Dog是实际类型

// 编译器检查:
// 1. 检查animal.eat()方法在Animal类中是否存在
// 2. 不关心实际运行时调用哪个实现
animal.eat();  // ✅ 编译通过(假设Animal有eat方法)
animal.bark(); // ❌ 编译错误(Animal没有bark方法,即使 Dog类中有bark方法也会报错)


// 运行时:JVM根据实际对象类型决定调用哪个方法
Animal animal1 = new Dog();    // 实际是Dog对象
Animal animal2 = new Cat();    // 实际是Cat对象

animal1.eat();  // 运行时调用 Dog.eat()
animal2.eat();  // 运行时调用 Cat.eat()
public interface Payment {
    // 接口中的方法默认是 public abstract
    void pay(double amount);
    boolean refund(double amount);

    // Java 8+ 默认方法 即多态时调用,实现类若没重写,就调用该接口的定义的
    default void printPaymentInfo() {
        System.out.println("支付接口");
    }

    // Java 8+ 静态方法
    static double calculateFee(double amount) {
        return amount * 0.01;  // 1%手续费
    }
}



public class AlipayPayment implements Payment {
    private String account;
    private double balance;

    public AlipayPayment(String account, double balance) {
        this.account = account;
        this.balance = balance;
    }

    @Override
    public void pay(double amount) {
        if (amount <= balance) {
            balance -= amount;
            System.out.println("支付宝支付成功: " + amount + "元");
            System.out.println("账户: " + account + ", 余额: " + balance);
        } else {
            System.out.println("支付宝余额不足");
        }
    }

    @Override
    public boolean refund(double amount) {
        balance += amount;
        System.out.println("支付宝退款: " + amount + "元");
        return true;
    }

    // 特有方法
    public void transfer(String toAccount, double amount) {
        System.out.println("向 " + toAccount + " 转账 " + amount + "元");
    }
}



public class WechatPayment implements  Payment{
    private String openId;
    private double balance;

    public WechatPayment(String openId, double balance) {
        this.openId = openId;
        this.balance = balance;
    }

    @Override
    public void pay(double amount) {
        if (amount <= balance) {
            balance -= amount;
            System.out.println("微信支付成功: " + amount + "元");
            System.out.println("用户: " + openId + ", 余额: " + balance);
        } else {
            System.out.println("微信余额不足");
        }
    }

    @Override
    public boolean refund(double amount) {
        balance += amount;
        System.out.println("微信退款: " + amount + "元");
        return true;
    }

    @Override
    public void printPaymentInfo() {
        System.out.println("微信支付 - 便捷支付方式");
    }

    // 特有方法
    public void sendRedPacket(double amount) {
        System.out.println("发送红包: " + amount + "元");
    }
}

@Test
public void test2(){
    System.out.println("\n=== 支付系统(接口多态)===");

    Payment[] payments = new Payment[2];
    payments[0] = new AlipayPayment("zhangsan@alipay.com", 1000);
    payments[1] = new WechatPayment("wx123456789", 800);

    // 统一支付操作
    for (Payment payment : payments) {
        System.out.println("\n--- 使用" + payment.getClass().getSimpleName() + " ---");
        payment.printPaymentInfo();  // 多态调用默认方法,实现类没有就调用接口默认,否则调用实现类
        payment.pay(200);           // 多态调用,实际执行的是各实现类的方法

        // 计算手续费(静态方法)
        double fee = Payment.calculateFee(200); //静态方法运行的是接口的
        System.out.println("手续费: " + fee);
        
        payment.transfer("lisi", 10); // 编译时会报错,因为接口中没有transfer方法,就算实现类里面有
    }

    new AlipayPayment("zhangsan@alipay.com", 1000).transfer("lisi", 10);
}

修饰符

final 修饰符
  •  final 修饰类: 禁止继承,防止被其他类扩展。
// final 类 - 不能被继承
final class StringUtils {
    // 工具类常用final,防止被继承和修改
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}

// 编译错误:不能继承final类
// class MyStringUtils extends StringUtils { }
  • final 修饰方法: 禁止子类重写该方法。
class Parent {
    // final实例方法 - 不能被子类重写
    public final void cannotOverride() {
        System.out.println("这是final方法,不能被重写");
    }
    
    // 普通方法 - 可以被子类重写
    public void canOverride() {
        System.out.println("可以被重写的方法");
    }
}

class Child extends Parent {
    // ❌ 编译错误:不能重写final方法
    // @Override
    // public void cannotOverride() { }
    
    // ✅ 可以重写非final方法
    @Override
    public void canOverride() {
        System.out.println("子类重写的方法");
    }
}
  • final 修饰变量: 一旦赋值后,就不能再修改(成为常量)。
// final实例变量 - 必须在构造器完成前初始化
private final String id = "bwf";
static 修饰符

static成员(方法和属性)属于类本身,而不是对象。

访问方式类访问对象访问推荐方式
static属性✅ 可以⚠️ 可以(不推荐)类名.属性
static方法✅ 可以⚠️ 可以(不推荐)类名.方法
非static属性❌ 不能✅ 可以对象.属性
非static方法❌ 不能✅ 可以对象.方法

接口 vs 抽象类

特性抽象类(Abstract Class)接口(Interface)
定义关键字abstract classinterface
继承/实现使用 extends 继承使用 implements 实现
多重继承❌ 不支持(单继承)✅ 支持(多实现)
构造器✅ 可以有❌ 不能有
成员变量任意访问修饰符默认 public static final
方法实现可以有具体方法Java 8前不能有,Java 8+可以有默认方法
方法修饰符任意访问修饰符默认 public abstract
设计目的代码复用,模板方法定义契约,解耦
设计层次"IS-A" 关系(是什么)"CAN-DO" 关系(能做什么)
使用场景紧密相关的类,共享代码不同体系的类,定义能力
// ========== 抽象类 ==========
abstract class Animal {
    // 可以有字段(任意修饰符)
    protected String name;
    private int age;
    public static final String TYPE = "动物";
    
    // 可以有构造器
    public Animal(String name) {
        this.name = name;
    }
    
    // 抽象方法(必须被子类实现)
    public abstract void makeSound();
    
    // 具体方法(可以被子类继承)
    public void eat() {
        System.out.println(name + " 正在吃东西");
    }
    
    // 静态方法
    public static void printType() {
        System.out.println("类型: " + TYPE);
    }
    
    // 私有方法
    private void internalMethod() {
        // 内部逻辑
    }
}

// ========== 接口 ==========
interface Flyable {
    // 常量(默认 public static final)
    int MAX_HEIGHT = 10000;  // 等价于 public static final int MAX_HEIGHT = 10000;
    
    // 抽象方法(Java 8前唯一允许的方法类型)
    void fly();  // 等价于 public abstract void fly();
    
    // Java 8+: 默认方法(有实现)
    default void glide() {
        System.out.println("滑翔中...");
    }
    
    // Java 8+: 静态方法
    static void printMaxHeight() {
        System.out.println("最大飞行高度: " + MAX_HEIGHT + "米");
    }
    
    // Java 9+: 私有方法
    private void log(String message) {
        System.out.println("日志: " + message);
    }
}