一、Java 基础语法
1.1 Java三大特性
Java 的三大特性是 封装(Encapsulation)、继承(Inheritance) 和 多态(Polymorphism)。这三大特性是面向对象编程(OOP)的核心思想,也是 Java 语言设计的基础。
- 封装(Encapsulation)
封装是将数据(属性)和行为(方法)绑定在一起,并隐藏内部实现细节的过程。通过封装,可以控制对类的内部状态的访问,从而提高代码的安全性和可维护性。- 实现方式:
- 使用 访问修饰符(如 private、protected、public)控制对类成员的访问。
- 提供 公共方法(如 getter 和 setter)来访问和修改私有属性。
- 优点:
- 安全性:隐藏内部实现细节,防止外部直接修改数据。
- 灵活性:可以在不改变外部接口的情况下修改内部实现。
- 可维护性:代码更易于理解和维护。
- 实现方式:
- 继承(Inheritance)
继承是指一个类(子类)可以继承另一个类(父类)的属性和方法。通过继承,可以实现代码的重用和扩展。- 实现方式:
- 使用 extends 关键字实现类与类之间的继承关系。
- 子类可以继承父类的非私有属性和方法。
- 子类可以重写(Override)父类的方法,以实现不同的行为。
- 优点:
- 代码重用:子类可以直接使用父类的属性和方法,减少重复代码。
- 扩展性:子类可以在父类的基础上添加新的属性和方法。
- 实现方式:
- 多态(Polymorphism)
多态是指同一个方法在不同对象中有不同的实现方式。- 实现方式:
- 编译时多态:通过方法重载(Overload)实现。
- 运行时多态:通过方法重写(Override)实现。
- 优点:
- 灵活性:同一个方法可以根据对象的不同表现出不同的行为。
- 可扩展性:新增子类时,无需修改现有代码。
- 实现方式:
1.2 多态的实现机制
在 Java 中,多态(Polymorphism) 是面向对象编程的核心特性之一,而 向上转型(Upcasting) 和 向下转型(Downcasting) 是实现多态的重要机制。
- 向上转型(Upcasting)
向上转型是指将子类对象赋值给父类引用变量。这种转型是自动的,不需要显式转换。- 特点:
- 自动转型:子类对象可以直接赋值给父类引用变量。
- 安全性:向上转型总是安全的,因为子类对象一定是父类类型。
- 功能限制:通过父类引用变量只能访问父类中定义的属性和方法,不能访问子类特有的属性和方法。
- 使用场景:
- 当需要将多个子类对象统一处理时,可以使用向上转型。
- 例如,将不同子类对象存储在父类类型的集合中。
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override void sound() { System.out.println("Dog barks"); } void fetch() { System.out.println("Dog fetches the ball"); } } public class Main { public static void main(String[] args) { // 向上转型 Animal myAnimal = new Dog(); // 子类对象赋值给父类引用变量 myAnimal.sound(); // 调用重写后的方法,输出 "Dog barks" // myAnimal.fetch(); // 编译错误,无法访问子类特有的方法 } }
- 特点:
- 向下转型(Downcasting)
向下转型是指将父类引用变量转换为子类类型。这种转型需要显式转换,并且可能会抛出 ClassCastException 异常。- 特点:
- 显式转型:需要使用强制类型转换。
- 风险性:如果父类引用变量实际指向的对象不是目标子类类型,会抛出 ClassCastException。
- 功能恢复:通过向下转型可以恢复子类特有的属性和方法。
- 使用场景:
- 当需要访问子类特有的方法或属性时,可以使用向下转型。
- 例如,从父类类型的集合中取出对象并转换为具体的子类类型。
public class Main { public static void main(String[] args) { // 向上转型 Animal myAnimal = new Dog(); // 向下转型 if (myAnimal instanceof Dog) { // 检查类型 Dog myDog = (Dog) myAnimal; // 强制类型转换 myDog.sound(); // 输出 "Dog barks" myDog.fetch(); // 输出 "Dog fetches the ball" } } }
- 特点:
1.3 基本数据类型
Java 提供了 8 种基本数据类型,它们是 Java 语言中最基础的数据存储单元。
基本类型 | 大小(字节 | 默认值 | 取值范围 |
---|---|---|---|
byte | 1 | 0 | -128 到 127 |
short | 2 | 0 | -32,768 到 32,767 |
int | 4 | 0 | -2³¹ 到 2³¹-1 |
long | 8 | 0L | -2⁶³ 到 2⁶³-1 |
float | 4 | 0.0f | 约 ±3.4e-38 到 ±3.4e+38 |
double | 8 | 0.0d | 约 ±1.7e-308 到 ±1.7e+308 |
char | 2 | ‘\u0000’ | 0 到 65,535(Unicode 字符) |
boolean | - | false | true 或 false |
- 特点
- 存储方式:基本类型直接存储数据值,存储在栈内存中。
- 性能:基本类型的操作效率高,因为它们是直接操作数据的。
- 默认值:基本类型有默认值(如 int 的默认值是 0)。
- 不支持面向对象特性:基本类型不是对象,不能调用方法或参与面向对象的操作。
1.4 包装类型
包装类型是对基本类型的封装,将基本类型包装成对象,以便可以使用面向对象的特性。
基本类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
- 特点
- 存储方式:包装类型是对象,存储在堆内存中。
- 功能:包装类型提供了许多实用的方法(如 Integer.parseInt()、Double.toString() 等)。
- 默认值:包装类型的默认值是 null。
- 支持面向对象特性:包装类型是对象,可以调用方法、参与集合操作等。
- 自动装箱和拆箱:
- 自动装箱:将基本类型自动转换为包装类型。
Integer num = 10; // 自动装箱
- 自动拆箱:将包装类型自动转换为基本类型。
int value = num; // 自动拆箱
- 自动装箱:将基本类型自动转换为包装类型。
1.5 访问修饰符
- public
- 访问范围:最大范围的访问权限。
- 特点:
- 被 public 修饰的成员可以在任何地方访问。
- 如果一个类被声明为 public,则该类可以被其他包中的类访问。
- protected
- 访问范围:
- 同一包内的类可以访问。
- 不同包中的子类可以访问。
- 特点:
- 主要用于继承场景,允许子类访问父类的成员。
- 访问范围:
- private
- 访问范围:最小范围的访问权限,仅限于当前类内部。
- 特点:
- 被 private 修饰的成员只能在当前类中访问。
- 常用于封装类的内部实现细节。
- 默认(无修饰符,包私有)
- 访问范围:同一包内的类可以访问。
- 特点:
- 如果没有显式指定访问修饰符,则使用默认访问权限。
- 默认访问权限的成员不能被其他包中的类访问。
1.6 接口与抽象类
在 Java 中,接口(Interface) 和 抽象类(Abstract Class) 都是实现抽象化的工具,但它们的设计目的和使用场景有所不同。
特性 | 抽象类(Abstract Class) | 接口(Interface) |
---|---|---|
关键字 | abstract | interface |
实例化 | 不能实例化 | 不能实例化 |
方法实现 | 可以包含抽象方法和具体方法 | Java 8 之前只能包含抽象方法,之后可以包含默认方法和静态方法 |
变量 | 可以包含普通变量和常量 | 只能包含常量(public static final) |
构造器 | 可以有构造器 | 不能有构造器 |
继承与实现 | 只能单继承(一个类只能继承一个抽象类) | 可以多实现(一个类可以实现多个接口) |
默认访问修饰符 | 方法可以是 public、protected、private 等 | 方法默认是 public abstract,变量默认是 public static final |
使用场景 | 适用于有共同行为和状态的类 | 适用于定义行为规范,不关心具体实现 |
1.7 方法重载与方法重写
在 Java 中,方法重载(Overloading) 和 方法重写(Overriding) 是多态性的两种表现形式。它们分别用于不同的场景,具有不同的规则和特点。
- 方法重载(Overloading)
方法重载是指在同一个类中定义多个同名方法,但这些方法的参数列表必须不同(参数类型、参数个数或参数顺序不同)。- 特点:
- 同一个类中:方法重载发生在同一个类中。
- 方法名相同:重载的方法必须具有相同的方法名。
- 参数列表不同:参数的类型、个数或顺序必须不同。
- 返回类型无关:方法重载与返回类型无关,可以相同也可以不同。
- 访问修饰符无关:方法重载与访问修饰符无关,可以相同也可以不同。
- 特点:
- 方法重写(Overriding)
方法重写是指子类重新定义父类中已有的方法,以实现不同的行为。- 特点:
- 父子类之间:方法重写发生在子类和父类之间。
- 方法名相同:重写的方法必须具有相同的方法名。
- 参数列表相同:参数的类型、个数和顺序必须完全相同。
- 返回类型兼容:子类方法的返回类型必须与父类方法的返回类型相同或是其子类(协变返回类型)。
- 访问修饰符不能更严格:子类方法的访问修饰符不能比父类方法更严格(例如,父类方法是 protected,子类方法不能是 private)。
- 异常不能更宽泛:子类方法抛出的异常不能比父类方法抛出的异常更宽泛。
- 特点:
二、Java常用函数
2.1 字符串操作函数
- length():
- 返回字符串的长度。
- 示例:
String str = "Hello"; int len = str.length(); // len = 5
- charAt(int index):
- 返回指定索引处的字符。
- 示例:
char ch = str.charAt(1); // ch = 'e'
- substring(int beginIndex, int endIndex):
- 返回从 beginIndex 到 endIndex-1 的子字符串。
- 示例:
String sub = str.substring(1, 4); // sub = "ell"
- indexOf(String str):
- 返回指定子字符串在原字符串中第一次出现的索引,未找到返回 -1。
- 示例:
int index = str.indexOf("lo"); // index = 3
- toLowerCase() 和 toUpperCase():
- 将字符串转换为小写或大写。
- 示例:
String lower = str.toLowerCase(); // lower = "hello" String upper = str.toUpperCase(); // upper = "HELLO"
- trim():
- 去除字符串两端的空白字符。
- 示例:
String trimmed = " Hello ".trim(); // trimmed = "Hello"
- replace(char oldChar, char newChar):
- 替换字符串中的字符。
- 示例:
String replaced = str.replace('l', 'L'); // replaced = "HeLLo"
- split(String regex):
- 根据正则表达式拆分字符串为数组。
- 示例:
String[] parts = "a,b,c".split(","); // parts = ["a", "b", "c"]
- equals(Object obj):
- 比较两个字符串的内容是否相等。
- 示例:
boolean isEqual = str.equals("Hello"); // isEqual = true
- equalsIgnoreCase(String str):
- 忽略大小写比较两个字符串的内容。
- 示例:
boolean isEqual = str.equalsIgnoreCase("hello"); // isEqual = true
2.2 集合操作函数
- add(E e):
- 向集合中添加元素。
- 示例:
List<String> list = new ArrayList<>(); list.add("Java");
- remove(Object o):
- 从集合中移除指定元素。
- 示例:
list.remove("Java");
- size():
- 返回集合的大小。
- 示例:
int size = list.size();
- get(int index):
- 返回指定索引处的元素。
- 示例:
String element = list.get(0);
- contains(Object o):
- 判断集合是否包含指定元素。
- 示例:
boolean contains = list.contains("Java");
- isEmpty():
- 判断集合是否为空。
- 示例:
boolean isEmpty = list.isEmpty();
- clear():
- 清空集合中的所有元素。
- 示例:
list.clear();
- sort(Comparator<? super E> c):
- 对列表进行排序。
- 示例:
list.sort(Comparator.naturalOrder());
2.3 数学计算函数
- Math.abs(int a):
- 返回绝对值。
- 示例:
int absValue = Math.abs(-10); // absValue = 10
- Math.max(int a, int b) 和 Math.min(int a, int b):
- 返回两个数中的最大值或最小值。
- 示例:
int max = Math.max(5, 10); // max = 10 int min = Math.min(5, 10); // min = 5
- Math.pow(double a, double b):
- 返回 a 的 b 次方。
- 示例:
double power = Math.pow(2, 3); // power = 8.0
- Math.sqrt(double a):
- 返回 a 的平方根。
- 示例:
double sqrt = Math.sqrt(16); // sqrt = 4.0
- Math.round(double a):
- 返回四舍五入后的值。
- 示例:
long rounded = Math.round(3.6); // rounded = 4
- Math.random():
- 返回一个 [0.0, 1.0) 之间的随机数。
- 示例:
double random = Math.random();
2.4 日期时间函数
- LocalDate.now():
- 获取当前日期。
- 示例:
LocalDate today = LocalDate.now();
- LocalTime.now():
- 获取当前时间。
- 示例:
LocalTime now = LocalTime.now();
- LocalDateTime.now():
- 获取当前日期和时间。
- 示例:
LocalDateTime current = LocalDateTime.now();
- DateTimeFormatter:
- 格式化日期时间。
- 示例:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formatted = current.format(formatter);
2.5 文件操作函数
- Files.readAllLines(Path path):
- 读取文件的所有行。
- 示例:
List<String> lines = Files.readAllLines(Paths.get("file.txt"));
- Files.write(Path path, byte[] bytes):
- 将字节数组写入文件。
- 示例:
Files.write(Paths.get("file.txt"), "Hello".getBytes());
- File.exists():
- 判断文件是否存在。
- 示例:
boolean exists = new File("file.txt").exists();