封装(Encapsulation)
- 使用 访问修饰符 控制可见性:
private:仅本类内部可见protected:本类、子类、同包可见public:任何地方可见- (默认)同包可见
- 通常将属性设为
private,提供公共的getter/setter方法。
public class BankAccount {
private double balance; // 私有化属性
public void deposit(double amount) {
if (amount > 0) balance += amount;
}
public double getBalance() { // 只读访问
return balance;
}
}
idea快捷键:Alt + Insert
继承(Inheritance)
- 使用
extends关键字 - Java 是单继承(一个子类只能有一个直接父类)
- 子类自动拥有父类非
private的属性和方法 - 可以重写(Override)父类方法
- super 关键字
- 访问父类的成员:
super.method()、super.field - 调用父类构造器:
super(参数)必须位于子类构造器的第一行
// 父类
public class Animal {
protected String name;
public void eat() {
System.out.println(name + " is eating.");
}
}
// 子类
public class Dog extends Animal {
// 新增属性
private String breed;
// 重写父类方法
@Override
public void eat() {
System.out.println(name + " is eating dog food.");
}
// 特有方法
public void bark() {
System.out.println("Woof!");
}
public Dog(String name, String breed) {
super(name); // 调用父类构造器
this.breed = breed;
}
}
多态(Polymorphism)
- 编译时多态:方法重载(同名不同参数)
- 运行时多态:方法重写 + 父类引用指向子类对象
方法重载:同一类中,方法名相同,参数列表不同(类型、个数、顺序)。
//重载
public int add(int a, int b) { return a+b; }
public double add(double a, double b) { return a+b; }
//方法重写 + 父类引用指向子类对象
Animal animal = new Dog("团团","喵喵"); //向上转型
animal.eat(); // 实际调用 Dog 的 eat()(动态绑定)
// animal.bark(); // 错误!父类引用不能调用子类特有方法
//判断一个对象是否是某个类 / 接口的实例
if (animal instanceof Dog) {
Dog d = (Dog) animal; //向下转型
d.bark();
}
抽象类(Abstract class)
- 用
abstract修饰,不能实例化 - 可以包含抽象方法(没有方法体)和具体方法
- 子类必须实现所有抽象方法(除非子类也是抽象类)
public abstract class Shape {
protected String color;
public abstract double area(); // 抽象方法
public void setColor(String color) { // 具体方法
this.color = color;
}
}
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
接口(interface)
- 使用
interface定义,完全抽象(Java 8+ 可以有默认方法和静态方法) - 类通过
implements实现接口,可以多实现(弥补单继承的不足) - 接口中的方法默认
public abstract,属性默认public static final
@FunctionalInterface // 这个注解的作用就是让编译器帮忙检查你这个接口是不是函数式接口(只有一个抽象方法)
public interface Flyable {
// 默认属性就是 public static final,可不写
public static final String name = "飞行";
Integer age = 20;
void fly(); // 抽象方法
//静态方法
static void fly2() {
System.out.println("静态方法");
}
// 默认方法(提供默认实现,子类可重写),默认方法可以有多个
default void land() {
System.out.println("Landing...");
}
}
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying.");
}
//接口的默认方法,可以不重写
@Override
public void land() {
Flyable.super.land();
}
}
函数式接口的要求: 当接口中只有一个抽象方法 , 默认方法(
default)和静态方法(static)不计入抽象方法
public static void main(String[] args) {
Flyable flyable = ()->{
System.out.println("鸟飞行");
};
flyable.fly();
}
final 关键字
final class:不能被继承final method:不能被子类重写final variable:变量不能改变(常量)
如果一个变量只被赋值一次,之后从未改变。那它就是 effectively final。
int z = 1; //只赋值一次,没有用final修饰,后续没有改变,这里的z就是 effectively final
//z++;
List<Integer> list = Arrays.asList(5,4,3,7,9);
list.forEach(i->{
System.out.println( i + z); //Lambda 中就可以直接使用z
});
// ------------------------------------------------
int z = 1;
z++; //如果 Z发生改变
List<Integer> list = Arrays.asList(5,4,3,7,9);
int finalZ = z; //进行拷贝一份,使他满足 只赋值一次,后续没有改变
list.forEach(i->{
System.out.println( i + finalZ);// z已经改变,只能使用z拷贝后的finalZ
});
内部类(Inner Class)
- 成员内部类
- 静态嵌套类
- 局部内部类
- 匿名内部类
import java.util.Arrays;
import java.util.List;
/**
* 演示四种内部类的综合案例
* 外部类:Outer
*/
public class Outer {
// 外部类的实例变量
private String outerInstanceField = "外部类实例变量";
// 外部类的静态变量
private static String outerStaticField = "外部类静态变量";
// ---------- 1. 成员内部类(非静态) ----------
public class MemberInner {
// 成员内部类中不能有静态成员(除常量外) (jdk16或者更高版本已允许)
public static String testObj = "<UNK>";
public void display() {
// 可以直接访问外部类的私有成员
System.out.println("成员内部类访问:" + outerInstanceField);
System.out.println("成员内部类访问:" + outerStaticField);
}
}
// ---------- 2. 静态嵌套类 ----------
public static class StaticNested {
public void display() {
// 只能访问外部类的静态成员,不能访问实例成员
System.out.println("静态嵌套类访问:" + outerStaticField);
// 下面一行编译错误(如果取消注释)
// System.out.println(outerInstanceField);
}
}
// ---------- 3. 演示局部内部类和匿名内部类的方法 ----------
public void demonstrateLocalAndAnonymous() {
// 局部变量(effectively final)
int localVar = 100;
// ---------- 3.1 局部内部类(定义在方法内) ----------
class LocalInner {
private String message = "局部内部类";
public void print() {
// 可以访问外部类成员
System.out.println(message + " 访问外部类实例变量:" + outerInstanceField);
// 可以访问所在方法的局部变量(必须是 effectively final)
System.out.println("局部内部类访问局部变量 localVar = " + localVar);
}
}
// 在方法内实例化局部内部类
LocalInner localInner = new LocalInner();
localInner.print();
// ---------- 3.2 匿名内部类(实现接口) ----------
Runnable anonymousRunnable = new Runnable() {
String message = "匿名内部类常量";
@Override
public void run() {
System.out.println(message+"匿名内部类访问外部类变量:" + outerInstanceField);
System.out.println("匿名内部类访问局部变量 localVar = " + localVar);
}
};
anonymousRunnable.run();
// 匿名内部类也可以直接作为参数传递
List<Integer> list = Arrays.asList(1, 2, 3);
list.forEach(new java.util.function.Consumer<Integer>() {
@Override
public void accept(Integer i) {
System.out.println("匿名内部类遍历元素:" + i + ", localVar=" + localVar);
}
});
}
// ---------- main 方法:演示所有内部类的使用 ----------
public static void main(String[] args) {
// 1. 成员内部类:必须先创建外部类实例,再通过该实例创建内部类对象
Outer outerObj = new Outer();
Outer.MemberInner memberInner = outerObj.new MemberInner();
System.out.println("===== 成员内部类 =====");
memberInner.display();
// 2. 静态嵌套类:直接通过外部类名创建,无需外部类实例
Outer.StaticNested staticNested = new Outer.StaticNested();
System.out.println("\n===== 静态嵌套类 =====");
staticNested.display();
// 3. 局部内部类 & 匿名内部类:通过外部类实例调用方法即可演示
System.out.println("\n===== 局部内部类 & 匿名内部类 =====");
outerObj.demonstrateLocalAndAnonymous();
}
}
除了静态嵌套类 ,其他内部类都保留着 类名.this,能获取到外部类的实例变量
| 变量类型 | 存储位置 | 生命周期 | 是否要求 final/effectively final |
|---|---|---|---|
| 外部类实例变量 | 堆(对象内) | 随外部类对象 | ❌ 不需要 |
| 外部类静态变量 | 方法区 | 随类(程序运行期间) | ❌ 不需要 |
| 方法局部变量 | 栈 | 方法执行期间 | ✅ 必须 effectively final |
枚举(enum)
表示一组常量,类型安全
- 枚举构造器总是 private(不能 public/protected),即不能从外部 new 枚举实例。
- 枚举默认继承 java.lang.Enum,因此不能再继承其他类,但可以实现接口。
- 枚举常量必须在所有字段和构造器之前声明,且最后一个常量后加分号(如果有额外内容)。
public enum Planet {
//调用构造器
MERCURY(3.303e23, 2.4397e6),
VENUS (4.869e24, 6.0518e6),
EARTH (5.976e24, 6.37814e6);
private final double mass; // 质量(kg)
private final double radius; // 半径(m)
// 构造器必须是 private(默认也是 private)
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
public double getMass() { return mass; }
public double getRadius() { return radius; }
// 计算表面重力加速度
public double surfaceGravity() {
final double G = 6.67300E-11;
return G * mass / (radius * radius);
}
}
System.out.println(Planet.EARTH.getMass()); // 5.976E24
System.out.println(Planet.EARTH.surfaceGravity()); // 约 9.8
枚举中可以定义抽象方法(每个常量单独实现)
public enum Operation {
PLUS {
@Override
public double apply(double x, double y) { return x + y; }
},
MINUS {
@Override
public double apply(double x, double y) { return x - y; }
},
TIMES {
@Override
public double apply(double x, double y) { return x * y; }
};
// 抽象方法
public abstract double apply(double x, double y);
}
double result = Operation.PLUS.apply(10, 5); // 15.0