Java基础语法,从小白到精通,收藏这篇就够了

目录

1、注释

2、关键字

3、数据类型

3.1、基础数据类型:

3.2、引用数据类型

4、运算符

5、分之与循环

5.1、分支

5.2、循环

6、类和对象

6.1、类的定义与对象的创建

6.2、空对象

6.3、类的属性

6.4、类的方法

6.5、类的基本结构

6.5.1 创建一个类的示例

6.5.2 抽象类示例

6.5.3 接口类示例

6.5.4 枚举类示例

7、静态

7.1、静态属性和静态方法

7.2、静态代码块

8、抽象类与接口

8.1、抽象类 Abstract Class

8.1.1 抽象类定义

8.1.2 继承抽象类

8.1.3 抽象类使用案例

8.2、接口 Interface

8.2.1 传统接口( Java 8 之前)

8.2.2 现代接口 (Java 8 之后)

8.2.3 接口的实现 implements

8.2.4 接口使用案例

8.3 抽象类时接口对比

8.3.1 语法对比

8.3.2 设计意图

8.4、实际应用场景

8.4.1 符合抽象类应用场景

8.4.2 符合接口应用场景

8.5. 选择指南

8.5.1 使用抽象类的情况:

8.5.2 使用接口的情况

8.5.3结合使用(常见模式)

9、包(package)

9.1、包是什么?

9.2、包的作用

9.3、包的声明

9.4、包名的组成规则

10、import

10.1 import是什么?

10.2 import 的语法和位置

10.3、import的三种使用方式

10.4、package 和 import 关键点总结

10.5、完整示例

11、final

11.1、final 修饰变量

11.2、final修饰方法

11.3、final修饰类

11.4、final注意事项

11.5、总结


1、注释

1.1 单行注释 //

1.2 多行注释 /**/

2、关键字
分类关键字
访问控制public, protected, private
类、方法、变量class, interface, enum, abstract, final, static, synchronized, volatile, transient, native, strictfp
流程控制if, else, switch, case, default, for, while, do, break, continue, return
异常处理try, catch, finally, throw, throws
包相关package, import
基本类型byte, short, int, long, float, double, char, boolean
面向对象this, super, new, instanceof, extends, implements
方法相关void, return
保留字const, goto
3、数据类型
3.1、基础数据类型:

(1)整数类型

    byte、short、int、long

(2)浮点型

    float、double

(3)字符类型

    char

(4)布尔类型

    boolean
数据类型关键字占用空间默认值取值范围说明
整型byte8 bit / 1 byte0-128 ~ 127小型整数
short16 bit / 2 byte0-32,768 ~ 32,767中等整数
int32 bit / 4 byte0-2³¹ ~ 2³¹-1 (约±21亿)最常用的整数类型
long64 bit / 8 byte0L-2⁶³ ~ 2⁶³-1大型整数,后缀加 Ll
浮点型float32 bit / 4 byte0.0f约 ±3.4e+38F单精度浮点数,后缀加 Ff
double64 bit / 8 byte0.0d约 ±1.7e+308最常用的浮点数类型,后缀 Dd 可省略
字符型char16 bit / 2 byte‘\u0000’0 ~ 65,535存储一个 Unicode 字符
布尔型boolean~1 bit (依赖JVM)falsetrue 或 false逻辑判断,大小没有精确指定
3.2、引用数据类型

(1)类

(2)接口

(3)数组

4、运算符

(1)一元运算符:++、–

(2)二元运算符:+、-、*、/、%

(3)三元运算符:exp1?exp2:exp3

(4)赋值运算符:=、+=、-=、*=、/=、%=

(5)关系运算符:==、!=、>、>=、<、<=

(6)逻辑运算符:&、|、^、!、&&、||

& 逻辑与(AND):两边都为true,结果才会为true。特点:无论左边是true与否,右边代码都会执行。

&&(短路与):两边都为true,结果才会为true。特点:左边为false,右边的表达式就不执行。

|(逻辑或 OR):任意一边为true,结果就为true。两边都会执行。

||(短路或):任意一边为true,结果就为true。左边为true,右边就不会执行。

^(逻辑异或):一真一假为true,两真两假为false。

||(逻辑非):与原来相反,原来是true,结果为false。反之亦然。

5、分之与循环
5.1、分支

(1)if- else if - else

若表达式语句为true,则执行里面的结构。

    public void game(){
        if (4>1){
            System.out.println("hello");
        } else if (4<1) {
            System.out.println("jjj");
        }else {
            System.out.println("qqqq");
        }
    }
    

(2)switch

    在Java中,**switch**语句是一种多分支选择结构,它可以根据一个表达式的值选择执行不同的代码块。这个表达式的值与定义在**switch**语句中的**case**标签进行比较,如果匹配,则执行相应的代码块。
public void game(){
        switch(3){
            case 1:{
                System.out.println("hello");
            }
            break;
            case 2:{
                System.out.println("sss");
            }
            break;
            case 3:{
                System.out.println("aaa");
            }
            break;
            default:
                System.out.println("no no no");
                break;
        }
    }



int month = 8;
String monthString;
switch (month) {
   case 1: monthString = "一月";
            break;
   case 2: monthString = "二月";
            break;
   case 3: monthString = "三月";
            break;
   case 4: monthString = "四月";
            break;
   case 5: monthString = "五月";
            break;
   case 6: monthString = "六月";
            break;
   case 7: monthString = "七月";
            break;
   case 8: monthString = "八月";
            break;
   case 9: monthString = "九月";
            break;
   case 10: monthString = "十月";
            break;
   case 11: monthString = "十一月";
            break;
   case 12: monthString = "十二月";
            break;
   default: monthString = "无效的月份";
            break;
}
System.out.println(monthString);
5.2、循环

(1)while(表达式){。。。}

public void game(){
        int k = 1;
        while (k < 3){
            System.out.println(k);
            k++;
        }
    }

(2)do{,}while(表达式)

 public void game(){
        int k = 1;
      do {
          System.out.println(k);
          k++;
      }while (k < 2);
      
    }

(3)for循环

    for(初始化表达式;条件表达式;更新表达式){  }
    public void game(){
        for (int i = 0; i <3; i++) {
            System.out.println(i);
        }
    }
6、类和对象
6.1、类的定义与对象的创建
    class  类名{。。。。}

    类名  对象名 = new 类名();
6.2、空对象
    Integer k = null;

    暂时不给对象创建空间时,可以使用空对象null,表示这个变量只被声明不被创建。
6.3、类的属性
public class Dog {
     String name; //类的属性只声明
     int age=10; // 类的属性声明并赋值
}

    变量在使用之前必须赋值,但是类的属性即使不初始化,也会被设置成默认值。如:

整数类型被默认初始值为0,浮点型为0.0,布尔类型为false,字符类型为“\u0000”,引用数据类型为null。

6.4、类的方法
public class Dog {

    void eat(){
        System.out.println(name + "吃饭了");
    }
}

6.5、类的基本结构
// 类声明
[访问修饰符] class 类名 [extends 父类] [implements 接口] {
    // 成员变量(属性)
    // 构造方法
    // 成员方法
    // 内部类
    // 静态代码块
    // 实例代码块
}
  • 命名规范:类名使用大驼峰(Studnet),变量、方法使用小驼峰(student)

  • 访问控制:成员变量尽量private,通过getter/setter访问

  • 封装性:隐藏内部实现细节,提供公共接口

  • 不可变性:尽量使用final修饰不可变字段(常量)

  • 文档注释:使用Javadoc为公共API添加文档

  • 异常处理:在适当的地方进行参数验证和异常抛出

  • 重写方法:正确重写equals、hashCode、toString方法

访问修饰符:

  • public:公共的,在任意地方都可以使用
  • protected:受保护的,在包内和子类可用
  • default:同包内可以用
  • private:仅本类可用

对于类的声明,只能使用 public 和 default(不写则默认)。

修饰符同类同包子类不同包描述
public任何地方都可访问
protected同包和子类可访问
default仅同包可访问
private仅本类可访问
  • 成员变量尽量使用private:保护数据完整性

  • 方法根据需要选择访问级别:公共API用public,内部实现用private

  • 构造方法控制:单例模式用private,工具类用private防止实例化

  • 接口方法默认public:接口中的方法默认是public abstract

  • 合理使用protected:为子类扩展提供便利,但不暴露给外部

正确使用访问修饰符可以提高代码的封装性、安全性和可维护性。

6.5.1 创建一个类的示例
package com.example.model;

import java.time.LocalDate;
import java.util.Objects;

/**
 * 学生类 - 演示完整的类结构
 */
public class Student extends Person implements Comparable<Student> {
    
    // ========== 成员变量 ==========
    
    // 静态变量(类变量)
    private static int studentCount = 0;
    public static final String SCHOOL_NAME = "某某大学";
    
    // 实例变量
    private String studentId;
    private String major;
    private int grade;
    private double gpa;
    private List<String> courses;
    
    // ========== 静态代码块 ==========
    static {
        System.out.println("Student类被加载");
        // 静态初始化代码
    }
    
    // ========== 实例代码块 ==========
    {
        this.courses = new ArrayList<>();
        studentCount++; // 每创建一个学生实例,计数加1
    }
    
    // ========== 构造方法 ==========
    
    // 默认构造方法
    public Student() {
        super(); // 调用父类构造方法
        this.studentId = "UNKNOWN";
        this.major = "未定专业";
    }
    
    // 带参数的构造方法
    public Student(String name, int age, String studentId, String major) {
        super(name, age); // 调用父类构造方法
        this.studentId = studentId;
        this.major = major;
        this.grade = 1; // 默认大一
    }
    
    // 全参数构造方法
    public Student(String name, int age, String studentId, 
                   String major, int grade, double gpa) {
        super(name, age);
        this.studentId = studentId;
        this.major = major;
        this.grade = grade;
        this.gpa = gpa;
    }
    
    // ========== 成员方法 ==========
    
    // Getter和Setter方法
    public String getStudentId() {
        return studentId;
    }
    
    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }
    
    public String getMajor() {
        return major;
    }
    
    public void setMajor(String major) {
        this.major = major;
    }
    
    public int getGrade() {
        return grade;
    }
    
    public void setGrade(int grade) {
        if (grade >= 1 && grade <= 4) {
            this.grade = grade;
        } else {
            throw new IllegalArgumentException("年级必须在1-4之间");
        }
    }
    
    public double getGpa() {
        return gpa;
    }
    
    public void setGpa(double gpa) {
        if (gpa >= 0.0 && gpa <= 4.0) {
            this.gpa = gpa;
        } else {
            throw new IllegalArgumentException("GPA必须在0.0-4.0之间");
        }
    }
    
    public List<String> getCourses() {
        return new ArrayList<>(courses); // 返回副本以保护内部数据
    }
    
    // 业务方法
    public void addCourse(String course) {
        if (course != null && !course.trim().isEmpty()) {
            this.courses.add(course);
        }
    }
    
    public void removeCourse(String course) {
        this.courses.remove(course);
    }
    
    public boolean isExcellentStudent() {
        return this.gpa >= 3.5;
    }
    
    public void promote() {
        if (this.grade < 4) {
            this.grade++;
        }
    }
    
    // 静态方法
    public static int getStudentCount() {
        return studentCount;
    }
    
    public static void displaySchoolInfo() {
        System.out.println("学校名称: " + SCHOOL_NAME);
    }
    
    // ========== 重写方法 ==========
    
    @Override
    public String toString() {
        return String.format("Student{学号='%s', 姓名='%s', 专业='%s', 年级=%d, GPA=%.2f}", 
                           studentId, getName(), major, grade, gpa);
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(studentId, student.studentId);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(studentId);
    }
    
    @Override
    public int compareTo(Student other) {
        return this.studentId.compareTo(other.studentId);
    }
    
    // ========== 内部类 ==========
    
    /**
     * 成绩记录内部类
     */
    public static class GradeRecord {
        private String courseName;
        private double score;
        private LocalDate examDate;
        
        public GradeRecord(String courseName, double score, LocalDate examDate) {
            this.courseName = courseName;
            this.score = score;
            this.examDate = examDate;
        }
        
        // Getter和Setter...
        public String getCourseName() { return courseName; }
        public double getScore() { return score; }
        public LocalDate getExamDate() { return examDate; }
    }
}
6.5.2 抽象类示例
public abstract class Shape {
    private String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // 抽象方法
    public abstract double calculateArea();
    public abstract double calculatePerimeter();
    
    // 具体方法
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    // 具体实现类
    public static class Circle extends Shape {
        private double radius;
        
        public Circle(String color, double radius) {
            super(color);
            this.radius = radius;
        }
        
        @Override
        public double calculateArea() {
            return Math.PI * radius * radius;
        }
        
        @Override
        public double calculatePerimeter() {
            return 2 * Math.PI * radius;
        }
    }
}
6.5.3 接口类示例
public interface Drawable {
    // 常量(默认 public static final)
    String DEFAULT_COLOR = "black";
    
    // 抽象方法
    void draw();
    
    // 默认方法(Java 8+)
    default void setColor(String color) {
        System.out.println("设置颜色为: " + color);
    }
    
    // 静态方法(Java 8+)
    static void displayInfo() {
        System.out.println("这是一个可绘制接口");
    }
    
    // 私有方法(Java 9+)
    private void logDrawing() {
        System.out.println("正在绘制...");
    }
}

// 实现接口
public class Rectangle implements Drawable {
    private int width;
    private int height;
    
    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public void draw() {
        System.out.printf("绘制矩形: %d x %d\n", width, height);
    }
}
6.5.4 枚举类示例
public enum Day {
    // 枚举常量
    MONDAY("星期一", 1),
    TUESDAY("星期二", 2),
    WEDNESDAY("星期三", 3),
    THURSDAY("星期四", 4),
    FRIDAY("星期五", 5),
    SATURDAY("星期六", 6),
    SUNDAY("星期日", 7);
    
    // 枚举属性
    private final String chineseName;
    private final int number;
    
    // 枚举构造方法
    Day(String chineseName, int number) {
        this.chineseName = chineseName;
        this.number = number;
    }
    
    // 枚举方法
    public String getChineseName() {
        return chineseName;
    }
    
    public int getNumber() {
        return number;
    }
    
    public boolean isWeekend() {
        return this == SATURDAY || this == SUNDAY;
    }
    
    public static Day getByNumber(int number) {
        for (Day day : values()) {
            if (day.number == number) {
                return day;
            }
        }
        throw new IllegalArgumentException("无效的数字: " + number);
    }
}
7、静态
7.1、静态属性和静态方法
public class Dog {
    static String nickName;
    static void drick(){
        System.out.println("喝饮料;。。。");
    }
    
}

    只与类有关的静态属性和方法,使用时直接使用 ===》 类名.静态变量,而非静态变量和方法必须创建对象才能使用。
public class Dog {
    static String nickName;
    static void drick(){
        System.out.println("喝饮料;。。。");
    }

     String name; //类的属性只声明
     int age=10; // 类的属性声明并赋值
    void eat(){
        System.out.println(name + "吃饭了");
    }

    public static void main(String[] args) {
        Dog.drick();
        Dog.eat();// 错误
    }
}
    可以在成员方法中使用静态方法和静态属性,但不能在静态方法中使用成语属性和方法。
7.2、静态代码块
public class Dog {

    static {
        System.out.println("开始运行。。。。");
    }

    public static void main(String[] args) {


    }
}

可以在类中使用 static 和 {}定义一个代码块,代码块会在类的信息加载完成后被自动调用。该代码块只会被调用一次。

7.3、实例化代码块 {纯大括号框起来的代码},特点如下:

package cn.kevinlu98.alipay.test1;

public class Dog {

    // 实例化代码块
    {

    }

    public static void main(String[] args) {


    }
}

  • 在每次创建对象时自动执行,即 new Student 时。。
  • 在构造方法之前执行
  • 适合放置多个构造方法共享的初始代码块
  • 可以访问示例变量和实例方法
  • 不能直接抛出检查性异常。
8、抽象类与接口
8.1、抽象类 Abstract Class
    抽象类不能被实例化,只能被继承。   abstract  、 extends
8.1.1 抽象类定义
// 抽象类声明
public abstract class Animal {
    // 属性(可以有具体实现)
    protected String name;
    protected int age;
    
    // 构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 抽象方法 - 没有方法体,子类必须实现
    public abstract void makeSound();
    
    // 具体方法 - 有方法体,子类可以直接使用或重写
    public void sleep() {
        System.out.println(name + "正在睡觉...");
    }
    
    // 具体方法
    public String getName() {
        return name;
    }
}
8.1.2 继承抽象类
// 继承抽象类
public class Dog extends Animal {
    private String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 调用父类构造方法
        this.breed = breed;
    }
    
    // 必须实现抽象方法
    @Override
    public void makeSound() {
        System.out.println(name + "汪汪叫!");
    }
    
    // 可以重写具体方法(可选)
    @Override
    public void sleep() {
        System.out.println(name + "蜷缩着睡觉...");
    }
    
    // 子类特有方法
    public void fetch() {
        System.out.println(name + "在接飞盘!");
    }
}

public class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }
    
    @Override
    public void makeSound() {
        System.out.println(name + "喵喵叫!");
    }
}
8.1.3 抽象类使用案例
public class AbstractClassTest {
    public static void main(String[] args) {
        // Animal animal = new Animal();  // ❌ 错误!不能实例化抽象类
        
        Animal dog = new Dog("旺财", 3, "金毛");
        Animal cat = new Cat("咪咪", 2);
        
        dog.makeSound();  // 旺财汪汪叫!
        dog.sleep();      // 旺财蜷缩着睡觉...
        
        cat.makeSound();  // 咪咪喵喵叫!
        cat.sleep();      // 咪咪正在睡觉...
        
        // 多态性
        Animal[] animals = {dog, cat};
        for (Animal animal : animals) {
            animal.makeSound();  // 运行时调用具体实现
        }
    }
}
8.2、接口 Interface
8.2.1 传统接口( Java 8 之前)
  • 常量:默认 public static final
  • 抽象方法: 默认 public abstract
// 接口声明
public interface Flyable {
    // 常量(默认 public static final)
    String TYPE = "飞行器";
    
    // 抽象方法(默认 public abstract)
    void fly();
    
    void land();
}

public interface Swimmable {
    void swim();
}
8.2.2 现代接口 (Java 8 之后)
public interface AdvancedFlyable {
    // 抽象方法
    void fly();
    
    // 默认方法 - 有方法体,实现类可以不重写
    default void takeOff() {
        System.out.println("准备起飞...");
        checkEquipment();
    }
    
    // 静态方法 - 通过接口名直接调用
    static void showInfo() {
        System.out.println("这是一个飞行接口");
    }
    
    // 私有方法 - Java 9+,接口内部使用
    private void checkEquipment() {
        System.out.println("检查设备...");
    }
}
    比Java8之前多了:默认方法、静态方法、私有方法
8.2.3 接口的实现 implements
// 实现单个接口
public class Bird implements Flyable {
    private String species;
    
    public Bird(String species) {
        this.species = species;
    }
    
    @Override
    public void fly() {
        System.out.println(species + "在天空中飞翔");
    }
    
    @Override
    public void land() {
        System.out.println(species + "降落在树枝上");
    }
}

// 实现多个接口
public class Duck implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("鸭子在低空飞行");
    }
    
    @Override
    public void land() {
        System.out.println("鸭子降落在水面上");
    }
    
    @Override
    public void swim() {
        System.out.println("鸭子在水中游泳");
    }
}

// 实现现代接口
public class Airplane implements AdvancedFlyable {
    private String model;
    
    public Airplane(String model) {
        this.model = model;
    }
    
    @Override
    public void fly() {
        System.out.println(model + "飞机在飞行");
    }
    
    // 可以不重写takeOff(),使用默认实现
    // 也可以重写
    @Override
    public void takeOff() {
        System.out.println(model + "在跑道上加速起飞");
        // checkEquipment();  // ❌ 私有方法不能在实现类中调用
    }
}
8.2.4 接口使用案例
public class InterfaceTest {
    public static void main(String[] args) {
        // 传统接口
        Flyable bird = new Bird("鸽子");
        bird.fly();
        bird.land();
        
        Duck duck = new Duck();
        duck.fly();
        duck.swim();
        
        // 现代接口
        AdvancedFlyable airplane = new Airplane("波音747");
        airplane.takeOff();  // 使用重写的默认方法
        airplane.fly();
        
        // 调用接口静态方法
        AdvancedFlyable.showInfo();
        
        // 访问接口常量
        System.out.println("类型: " + Flyable.TYPE);
    }
}
8.3 抽象类时接口对比
8.3.1 语法对比
特性抽象类接口
关键字abstract classinterface
继承/实现extendsimplements
方法类型抽象方法 + 具体方法抽象方法 + 默认方法 + 静态方法
构造方法
字段任意类型只能是常量 (public static final)
多继承单继承多实现
访问修饰符任意默认 public
8.3.2 设计意图
// 抽象类:表示 "is-a" 关系,代码复用
// is-a” 关系 (是一个/是一种)
// 这种关系描述的是继承和分类。它表示一个类是另一个类的特化或子类型。

abstract class Vehicle {
    protected String brand;
    protected int speed;
    
    public Vehicle(String brand) {
        this.brand = brand;
    }
    
    // 所有交通工具都有启动行为,但具体实现不同
    public abstract void start();
    
    // 共同的行为,可以复用
    public void stop() {
        System.out.println(brand + "停止运行");
        this.speed = 0;
    }
}

// 接口:表示 "has-capability" 关系,定义能力
// “has-capability” 关系 (有能力做)
// 这种关系描述的是能力或契约。它表示一个类能够执行某些操作或遵守某个契约,而不关心这个类本身是什 // 么。即你能按照这个 方法名、返回值类型 具体实现这个方法,并返回正确类型


interface Electric {
    void charge();
    int getBatteryLevel();
}

interface Autonomous {
    void selfDrive();
    void autoPark();
}

// 具体类:既是交通工具,又有电动和自动驾驶能力
class Tesla extends Vehicle implements Electric, Autonomous {
    private int batteryLevel;
    
    public Tesla() {
        super("Tesla");
        this.batteryLevel = 100;
    }
    
    @Override
    public void start() {
        System.out.println("特斯拉静音启动");
    }
    
    @Override
    public void charge() {
        System.out.println("特斯拉充电中...");
        batteryLevel = 100;
    }
    
    @Override
    public int getBatteryLevel() {
        return batteryLevel;
    }
    
    @Override
    public void selfDrive() {
        System.out.println("开启自动驾驶模式");
    }
    
    @Override
    public void autoPark() {
        System.out.println("自动泊车中...");
    }
}
8.4、实际应用场景
8.4.1 符合抽象类应用场景
// 模板方法模式
public abstract class DataProcessor {
    // 模板方法 - 定义算法骨架
    public final void process() {
        readData();
        transformData();
        saveData();
        cleanup();
    }
    
    // 具体步骤
    private void readData() {
        System.out.println("读取数据...");
    }
    
    // 抽象方法 - 由子类实现
    protected abstract void transformData();
    
    private void saveData() {
        System.out.println("保存数据...");
    }
    
    // 钩子方法 - 子类可以选择性重写
    protected void cleanup() {
        System.out.println("清理资源...");
    }
}

// 具体实现
public class CSVProcessor extends DataProcessor {
    @Override
    protected void transformData() {
        System.out.println("转换CSV数据...");
    }
}

public class JSONProcessor extends DataProcessor {
    @Override
    protected void transformData() {
        System.out.println("转换JSON数据...");
    }
    
    @Override
    protected void cleanup() {
        System.out.println("JSON处理器特殊清理...");
    }
}
8.4.2 符合接口应用场景
// 策略模式
public interface PaymentStrategy {
    boolean pay(double amount);
}

// 具体策略
public class CreditCardPayment implements PaymentStrategy {
    @Override
    public boolean pay(double amount) {
        System.out.println("信用卡支付: $" + amount);
        return true;
    }
}

public class PayPalPayment implements PaymentStrategy {
    @Override
    public boolean pay(double amount) {
        System.out.println("PayPal支付: $" + amount);
        return true;
    }
}

public class CryptoPayment implements PaymentStrategy {
    @Override
    public boolean pay(double amount) {
        System.out.println("加密货币支付: $" + amount);
        return true;
    }
}

// 使用策略
public class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }
    
    public void checkout(double amount) {
        if (paymentStrategy.pay(amount)) {
            System.out.println("支付成功!");
        }
    }
}
8.5. 选择指南
8.5.1 使用抽象类的情况:
  • 需要在相关的类之间共享代码

  • 需要定义非静态或非final的字段

  • 需要定义除public之外的访问权限

  • 有共同的状态或行为需要被继承

8.5.2 使用接口的情况
  • 不相关的类需要实现相同的行为

  • 需要指定特定数据类型的行为,但不关心谁实现它

  • 需要多重继承的行为

  • 定义API契约,不关心具体实现

8.5.3结合使用(常见模式)
// 抽象类实现基本功能,接口定义扩展能力
abstract class Bird {
    public abstract void sing();
}

interface Flyable {
    void fly();
}

interface Swimmable {
    void swim();
}

class Sparrow extends Bird implements Flyable {
    @Override
    public void sing() {
        System.out.println("麻雀叽叽喳喳");
    }
    
    @Override
    public void fly() {
        System.out.println("麻雀飞翔");
    }
}

class Penguin extends Bird implements Swimmable {
    @Override
    public void sing() {
        System.out.println("企鹅叫声");
    }
    
    @Override
    public void swim() {
        System.out.println("企鹅游泳");
    }
}

总结

  • 抽象类:侧重于代码复用和"是什么"的关系,有构造方法,单继承

  • 接口:侧重于定义契约和"能做什么"的关系,无构造方法,多实现

  • 现代接口:功能更强大,支持默认方法、静态方法、私有方法

  • 选择原则:考虑"is-a"用抽象类,考虑"has-capability"用接口

9、包(package)
9.1、包是什么?
    包本质上就是文件系统的 **文件夹** 和 **目录** 。他是用来管理类(Class)和接口(interface)的一种机制。
9.2、包的作用

9.2.1、避免命名冲突:不同包中可以存在同名的类。包提供了命名空间,使得同名类可以共存。例如,你可以在 com.utils.Datejava.sql.Date 中同时使用 Date 类而不会冲突。

以下为例子讲解

场景:两个不同的 Date 类

假设我们有两个包:

  • com.utils - 包含我们自定义的 Date 类

  • 使用标准的 java.sql.Date

自定义Date类: com/utils/Date.java

package com.utils;

public class Date {
    private String customDate;
    
    public Date(String date) {
        this.customDate = date;
    }
    
    public void printCustomDate() {
        System.out.println("Custom Date: " + customDate);
    }
    
    public String getCustomDate() {
        return customDate;
    }
}

使用场景1:使用完全限定名避免冲突

MainWithFullQualified.java

import com.utils.Date; // 导入我们自定义的 Date

public class MainWithFullQualified {
    public static void main(String[] args) {
        // 使用自定义的 Date 类
        com.utils.Date myDate = new com.utils.Date("2024-01-15");
        myDate.printCustomDate();
        
        // 使用 java.sql.Date - 使用完全限定名
        java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
        System.out.println("SQL Date: " + sqlDate);
        
        // 使用 java.util.Date - 使用完全限定名
        java.util.Date utilDate = new java.util.Date();
        System.out.println("Util Date: " + utilDate);
    }
}

使用场景2:只导入一个另外一个使用完全限定名

import java.util.Date; // 只导入 java.util.Date

public class MainWithOneImport {
    public static void main(String[] args) {
        // 可以直接使用 java.util.Date
        Date utilDate = new Date();
        System.out.println("Util Date: " + utilDate);
        
        // 自定义的 Date 需要使用完全限定名
        com.utils.Date myDate = new com.utils.Date("2024-01-15");
        myDate.printCustomDate();
        
        // java.sql.Date 也需要使用完全限定名
        java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
        System.out.println("SQL Date: " + sqlDate);
    }
}

使用场景3:❌ 错误的方式,同时导入两个同名类

import java.util.Date;
import com.utils.Date; // 编译错误!冲突!

public class MainConflict {
    public static void main(String[] args) {
        // 编译器不知道你要用哪个 Date
        Date date = new Date(); // 歧义!
    }
}

错误编译信息:

The type Date is ambiguous

“Date”类型存在歧义

在实际项目使用示例:

package com.company.service;

import java.util.List;
import java.util.ArrayList;
// 注意:我们没有导入任何 Date 类

public class EmployeeService {
    
    public void processEmployeeData() {
        // 使用 java.util.Date 处理逻辑日期
        java.util.Date currentDate = new java.util.Date();
        System.out.println("Processing at: " + currentDate);
        
        // 使用自定义的 Date 处理业务特定日期格式
        com.utils.Date businessDate = new com.utils.Date("Q4-2024");
        businessDate.printCustomDate();
        
        // 使用 java.sql.Date 处理数据库日期
        java.sql.Date dbDate = new java.sql.Date(currentDate.getTime());
        System.out.println("DB Date: " + dbDate);
        
        List<String> employees = new ArrayList<>();
        employees.add("John Doe");
        // ... 其他业务逻辑
    }
    
    // 方法重载,使用不同的 Date 类型
    public void setHireDate(java.sql.Date sqlDate) {
        // 处理数据库日期
    }
    
    public void setReviewDate(com.utils.Date customDate) {
        // 处理业务自定义日期
    }
}

总结:

  • 使用完全限定名(包名 + 类名)

  • 只导入一个常用的类,其他使用完全限定名

  • 都不导入,全部使用完全限定名

9.2.2 访问控制

    结合 protected 和默认(包级私有)访问权限,包可以控制哪些类可以被其他包中的类访问。即Java类使用不同访问修饰符,包就控制访问权限不同。

9.2.3 类和接口的分类组织

    将功能相似或相关的类与接口组织在同一个包中,使项目结构更清晰,便于查找和维护。例如,所有与网络操作相关的类可以放在 **net** 包中,与数据库操作相关的放在 **dao** 包中。
9.3、包的声明
    在 Java 源文件(.java 文件)的**第一行(注释除外)**,使用 `package` 关键字来声明该文件中的所有类所属的包。

    **语法:**
package 包名;
    **示例:**  
    假设我们有一个 `Employee.java` 文件:
// 声明这个类属于 com.company.hr 包
package com.company.hr;

public class Employee {
    // ... 类的具体内容
}

编译后,Employee.class 文件必须位于 com/company/hr/ 目录下。

9.4、包名的组成规则
    包名是唯一标识一个包的字符串,遵循以下规则和约定:

9.4.1 全部小写

    这是 Java 的命名约定,以避免与类名或接口名冲突。

9.4.2 互联网域名反写(推荐)**

    为了确保全球唯一性,通常使用自己公司或组织拥有的**互联网域名的反写形式**作为包名的前缀。
  • 示例:如果你的公司域名是 google.com,那么你的包名应该以 com.google 开头。
  • 示例:一个开源项目在 github.com/username/myproject,包名可以是 com.github.username.myproject。

9.4.3 后续部分

    在反写的域名之后,可以根据项目、模块、功能来继续定义子包。
  • 示例:com.company.projectname.dao (数据访问层)
  • 示例:com.company.projectname.service (业务逻辑层)
  • 示例:com.company.projectname.controller (Web控制层)
  • 示例:com.company.projectname.utils (工具类)

9.4.4 合法标识符

    包名的每一部分(由点 . 分隔)必须是合法的 Java 标识符,不能是关键字(如 int, class)。

合法的包名示例:

  • java.util
  • com.sun.net
  • org.apache.commons.lang3
  • myapp (对于非常小的个人项目可以这样,但不推荐用于正式项目)

不合法的包名示例:

  • com.company.my-app (包含非法字符 -)
  • int.util (int 是关键字)
  • com.company.123utils (以数字开头)
10、import
10.1 import是什么?
    import 语句用于在当前的源文件中 **引入** 其他包中的类或整个包。这样,你在代码中就可以直接使用类的简单名称(如 ArrayList),而不需要使用完全限定名(如 java.util.ArrayList)。
10.2 import 的语法和位置
     import 语句写在 package 语句之后,任何类定义之前。
import package1[.package2...].(ClassName|*);
10.3、import的三种使用方式

10.3.1 导入单个类

import java.util.ArrayList; // 只导入 ArrayList 一个类

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(); // 可以直接使用
    }
}

10.3.2. 导入整个包(使用通配符 *

import java.util.*; // 导入 java.util 包下的所有类

public class Test {
    public static void main(String[] args) {
        // 现在可以使用 java.util 包下的任何类,如 ArrayList, Scanner, Date 等
        ArrayList<String> list = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
    }
}

注意:使用 * 并不会导致性能下降,也不会导入子包。它只是让编译器知道,当遇到一个不认识的类时,可以去这些包里找。

10.3.3. 不使用 import,使用完全限定名
你可以完全不使用 import,但在代码中每次使用该类时都必须写出完整的包名。

public class Test {
    public static void main(String[] args) {
        // 不使用 import,直接使用完全限定名
        java.util.ArrayList<String> list = new java.util.ArrayList<>();
        java.util.Date today = new java.util.Date();
    }
}

10.3.4 静态导入(Static Import)

    从 Java 5 开始,可以使用 `import static` 来导入一个类的静态成员(静态变量和静态方法)。

语法:

import static package.ClassName.staticMemberName;
import static package.ClassName.*; // 导入所有静态成员

示例:

import static java.lang.Math.PI; // 导入 PI
import static java.lang.Math.pow; // 导入 pow 方法
// import static java.lang.Math.*; // 或者一次性导入所有静态成员

public class Circle {
    public double getArea(double radius) {
        return PI * pow(radius, 2); // 可以直接使用 PI 和 pow,无需 Math.PI 和 Math.pow
    }
}
10.4、package 和 import 关键点总结
特性说明
package声明类所在的包,必须在文件第一行。
import引入其他包的类,在 package 之后,类定义之前。
包名通常为反写的域名,全部小写,用点分隔。
完全限定名包名.类名,如 java.util.ArrayList
通配符 *导入一个包下的所有类,但不包括子包。
import static用于导入类的静态成员,简化代码。
默认导入所有 Java 程序都默认导入了 java.lang.* 包(如 String, System)。
10.5、完整示例
MyProject/
└── src/
    └── com/
        └── company/
            └── app/
                ├── Main.java
                ├── model/
                │   └── User.java
                └── utils/
                    └── StringUtil.java

文件夹/目录结构: D:\MyProject\src\com\company\app\model\User.java

User.java

package com.company.app.model; // 声明包

public class User {
    private String name;
    // ... getters and setters
}

StringUtil.java

package com.company.app.utils; // 声明包

public class StringUtil {
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}

Main.java

package com.company.app; // 声明包

// 导入其他包中的类
import com.company.app.model.User;
import static com.company.app.utils.StringUtil.isEmpty; // 静态导入

public class Main {
    public static void main(String[] args) {
        User user = new User(); // 直接使用 User
        user.setName("Alice");

        if (isEmpty(user.getName())) { // 直接使用 isEmpty 方法
            System.out.println("Name is empty!");
        } else {
            System.out.println("Hello, " + user.getName());
        }
    }
}
11、final
11.1、final 修饰变量
    final修饰的变量,一旦被赋值,就不能进行修改。(即变成常量)

· (1)基本类型变量

final int MAX_VALUE = 100;
// MAX_VALUE = 200; // 编译错误,不能重新赋值

final double PI = 3.14159;

·(2) 引用类型变量

final List<String> list = new ArrayList<>();
list.add("Hello"); // 可以,修改对象内容
list.add("World");

// list = new ArrayList<>(); // 编译错误,不能重新指向其他对象

·(3) final 成员变量

    必须在构造方法结束前完成初始化或者直接初始化。
public class MyClass {
    private final int value; // 必须在构造器中初始化
    
    public MyClass(int value) {
        this.value = value;
    }
    
    // 或者直接初始化
    private final String name = "default";
}

· (4)static final 常量

public class Constants {
    public static final String APP_NAME = "MyApp";
    public static final int MAX_USERS = 1000;
}
11.2、final修饰方法
    final方法不能被子类重写。
class Parent {
    // final 方法,不能被子类重写
    public final void show() {
        System.out.println("这是父类的final方法");
    }
    
    public void display() {
        System.out.println("这是父类的普通方法");
    }
}

class Child extends Parent {
    // @Override
    // public void show() { } // 编译错误,不能重写final方法
    
    @Override
    public void display() { // 可以重写
        System.out.println("子类重写的方法");
    }
}
11.3、final修饰类
    final类不能被继承。
final class StringUtils {
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}

// class ExtendedUtils extends StringUtils { } // 编译错误,不能继承final类
11.4、final注意事项

(1)final与static final区别

  •       final:不可重复赋值
    
  •       static final:类常量,在类加载时初始化
    

(2)final引用类型

  引用不能改变,但对象内容可以修改
11.5、总结

final 关键字提供了不同级别的"不可变性":

  • final 变量:引用不可变

  • final 方法:行为不可变(不能被重写)

  • final 类:结构不可变(不能被继承)

final 和 static final 核心区别总结:

特性finalstatic final
归属级别实例级别类级别
内存分配堆内存方法区(元空间)
初始化时机对象实例化时类加载时
初始化位置构造方法中/声明时声明时/静态代码块
共享性每个对象独享一份所有对象共享一份
生命周期随对象创建/销毁随类加载/卸载

纯个人笔记,仅供参考,不保证内容完全准确性。如有疏漏,欢迎指正。

说真的,这两年看着身边一个个搞Java、C++、前端、数据、架构的开始卷大模型,挺唏嘘的。大家最开始都是写接口、搞Spring Boot、连数据库、配Redis,稳稳当当过日子。

结果GPT、DeepSeek火了之后,整条线上的人都开始有点慌了,大家都在想:“我是不是要学大模型,不然这饭碗还能保多久?”

先给出最直接的答案:一定要把现有的技术和大模型结合起来,而不是抛弃你们现有技术!掌握AI能力的Java工程师比纯Java岗要吃香的多。

即使现在裁员、降薪、团队解散的比比皆是……但后续的趋势一定是AI应用落地!大模型方向才是实现职业升级、提升薪资待遇的绝佳机遇!

如何学习AGI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享**

一、2025最新大模型学习路线

一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。

我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

L1级别:AI大模型时代的华丽登场

L1阶段:我们会去了解大模型的基础知识,以及大模型在各个行业的应用和分析;学习理解大模型的核心原理,关键技术,以及大模型应用场景;通过理论原理结合多个项目实战,从提示工程基础到提示工程进阶,掌握Prompt提示工程。

L2级别:AI大模型RAG应用开发工程

L2阶段是我们的AI大模型RAG应用开发工程,我们会去学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。

L3级别:大模型Agent应用架构进阶实践

L3阶段:大模型Agent应用架构进阶实现,我们会去学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造我们自己的Agent智能体;同时还可以学习到包括Coze、Dify在内的可视化工具的使用。

L4级别:大模型微调与私有化部署

L4阶段:大模型的微调和私有化部署,我们会更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调;并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。

整个大模型学习路线L1主要是对大模型的理论基础、生态以及提示词他的一个学习掌握;而L3 L4更多的是通过项目实战来掌握大模型的应用开发,针对以上大模型的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。

二、大模型经典PDF书籍

书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础(书籍含电子版PDF)

三、大模型视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

四、大模型项目实战

学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

五、大模型面试题

面试不仅是技术的较量,更需要充分的准备。

在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值