Java 5——final 抽象 接口

final

final修饰变量

基本用法

被final修饰的变量不可以被改变,又被称为常量

java 复制代码
final double PI = 3.14159;
PI = 3.14;   // 编译错误:不能再次赋值
空白 final(Blank final)

声明时不赋初值,但必须在构造方法或初始化块中完成赋值,且只能赋值一次

java 复制代码
class Circle {
    final double PI;           // 空白 final
    Circle() {
        PI = 3.14159;          // 构造方法中赋值
    }
}
final 修饰引用类型变量

引用变量本身不能再指向其他对象

但对象的内容(成员变量)仍可改变(除非对象的类做了不可变设计)

java 复制代码
final StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");      // ✅ 允许,对象内容改变
sb = new StringBuilder(); // ❌ 错误:引用不能改变
final 修饰成员变量

实例变量:必须显式赋值或在构造方法中赋值

静态变量:必须显式赋值或在静态代码块中赋值

java 复制代码
class Example {
    final int a = 10;           // 直接赋值
    final int b;                // 空白 final,需在构造器中赋值
    static final int C = 100;   // 静态常量
    static final int D;         // 空白 static final,需在静态块中赋值

    Example() { b = 20; }
    static { D = 200; }
}
局部变量

局部变量被 final 修饰后,值不能改变

java 复制代码
public void method() {
    final int x = 5;
    x = 6;   // 错误
}
方法参数

方法参数被 final 修饰后,在方法体内不能改变参数引用

java 复制代码
public void print(final int value) {
    // value = 10;   // 错误
    System.out.println(value);
}

final修饰方法

被final修饰的方法不可以被重写

主要目的:防止子类修改该方法的行为

注意:final 方法仍可以被继承,只是子类不能重写

java 复制代码
class Parent {
    public final void show() {
        System.out.println("Parent show");
    }
}

class Child extends Parent {
    // public void show() { }   // 编译错误:不能重写 final 方法
}

private 方法隐式是 final 的(因为子类不可见),但通常不写 final构造方法不能是 final(构造方法不能被继承)。

final修饰类

被final修饰的类不可以被继承

典型例子:StringIntegerSystem

java 复制代码
final class FinalClass {
    // 类体
}

// class SubClass extends FinalClass { }   // 编译错误:不能继承 final 类

final 类的所有方法隐式也是 final 的(因为无法被重写),但成员变量可以是普通的

finalstatic 的区别

特性 final static
作用 不可改变(值、方法、类) 属于类,不依赖对象
修饰变量 只能赋值一次(常量) 类变量,所有对象共享一份
修饰方法 不能被子类重写 类方法,不能被子类重写(隐藏)
修饰类 不能被继承 不能修饰外部类(可修饰内部类)
常见组合 static final 表示全局常量 -

全局变量通常写成 public static final,例如 Math.PI

java 复制代码
public static final double PI = 3.141592653589793;

总结就是不可变

final 与不可变性(Immutability)

final 只是保证引用不可变,并不保证对象内容不可变

真正的不可变类要求:

1.类声明为 final(防止子类修改行为)

2.所有成员变量为 private final

3.不提供任何修改成员变量的方法(setter)

4.如果有可变成员(如 Date、集合),应返回其副本或不可变视图

java 复制代码
public final class ImmutablePerson {
    private final String name;
    private final int age;
    public ImmutablePerson(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() { return name; }
    public int getAge() { return age; }
}

抽象

抽象:现实中不存在的东西

在Java中的抽象表示只声明,不实现

抽象方法

抽象方法:使用abstract来修饰,不可以有方法体,直接用分号结束

抽象类:如果一个类中有抽象方法,那么这个类必须是一个抽象类

特点:

1.抽象类不可以创建对象

2.抽象类的子类,必须重写父类中的抽象方法,否则子类必须也是抽象类

3.抽象方法不能被 privatefinalstatic 修饰

抽象类

通过抽象类可以强制要求子类中必须有哪些方法

抽象类不能被实例化 (不能 new

抽象类的构造方法用于被子类调用(super

抽象类可以没有抽象方法(但通常至少有一个抽象方法)

抽象类可以包含成员变量、常量、构造方法、具体方法、静态方法等

抽象类中可以有正常的方法

java 复制代码
public abstract class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    // 抽象方法
    public abstract void sound();
    
    // 具体方法
    public void sleep() {
        System.out.println(name + "在睡觉");
    }
}
继承抽象类

子类继承抽象类后,必须:

实现所有抽象方法(除非子类也是抽象类)

可以使用 super 调用父类构造方法

java 复制代码
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    @Override
    public void sound() {
        System.out.println(name + "汪汪叫");
    }
}

class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }
    @Override
    public void sound() {
        System.out.println(name + "喵喵喵");
    }
}
常见误区

1.误区:抽象类必须包含抽象方法。

正解:抽象类可以没有抽象方法(例如作为工具类禁止实例化)。

2.误区:抽象类不能有构造方法。

正解:有构造方法,用于子类初始化。

3.误区:abstractfinal 可以同时修饰方法。

正解:不能,final 方法不能被重写,而抽象方法必须被重写,矛盾。

4.误区:抽象类可以实例化匿名内部类。

正解:这是创建了匿名子类的对象,不是抽象类本身的实例。

接口

接口实际上是一种特殊的抽象类

接口中所有的方法都是抽象方法

接口使用interface来声明,接口中的方法默认是 public abstract(可省略),成员变量默认是 public static final(常量)

java 复制代码
public interface Animal {
    // 常量(默认 public static final)
    String TYPE = "动物";

    // 抽象方法(默认 public abstract)
    void eat();
    void sleep();
}

类只能单继承,接口支持多实现

使用 implements 关键字,一个类可以实现多个接口(多实现)。必须实现所有抽象方法(除非该类是抽象类)

java 复制代码
public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
    @Override
    public void sleep() {
        System.out.println("狗睡觉");
    }
}

接口同样具有多态性

接口可以把很多不相关的内容进行整合

特点:

1.接口中所有的方法都是抽象方法,都是公开的

2.接口中所有的变量都是全局静态变量

特性 说明
接口不能实例化 不能 new 接口名(),但可以用实现类对象赋值给接口引用(多态)
接口没有构造方法 不能被 new,也不需要有构造方法
接口中的方法默认修饰符 public abstract(可省略)
接口中的成员变量默认修饰符 public static final(可省略),必须显式赋值
一个类可以实现多个接口 解决 Java 单继承的局限
接口可以继承多个接口 使用 extends,接口之间可以多继承
接口可以包含默认方法 Java 8 引入,使用 default 关键字,提供默认实现,不强制实现类重写
接口可以包含静态方法 Java 8 引入,使用 static 关键字,通过接口名调用
接口可以包含私有方法 Java 9 引入,用于默认方法或静态方法内部复用代码
接口的多实现

1.一个类可以实现多个接口。

2.如果多个接口有相同签名的默认方法,实现类必须重写该方法(或指定调用哪个父接口的默认方法)。

3.如果多个接口有相同签名的抽象方法,实现类只需实现一次

java 复制代码
interface Flyable {
    void fly();
}
interface Swimmable {
    void swim();
}
class Duck implements Flyable, Swimmable {
    @Override
    public void fly() { System.out.println("鸭子飞"); }
    @Override
    public void swim() { System.out.println("鸭子游泳"); }
}
接口与抽象类的区别
特性 接口(interface) 抽象类(abstract class)
关键字 interface abstract class
实例化 不能 不能
成员变量 默认 public static final(常量) 可以是普通变量、常量
构造方法 有,供子类调用
抽象方法 默认 public abstract 可以是 protectedpublic
具体方法 Java 8+ 可以有 default/static 方法 可以有任意具体方法
私有方法 Java 9+ 允许 允许
继承/实现 一个类可以实现多个接口 一个类只能继承一个抽象类(单继承)
设计意图 定义"能做什么"(can-do)能力契约 定义"是什么"(is-a),复用代码
常见误区
误区 正确理解
接口中不能有方法体 Java 8+ 可以有 defaultstatic 方法体
接口中的方法必须是 public 默认就是 public,不能是 protected / private(除非 Java 9+ 的私有方法)
接口可以实例化 不能,但可以用匿名内部类创建接口的匿名实现类
接口中的变量可以修改 接口中的变量默认是 final,不能修改
实现接口必须重写所有方法 如果实现类是抽象类,可以不重写
相关推荐
Andy1 小时前
C++ 容器适配器_栈_队列_双端队列
开发语言·网络·c++
吴声子夜歌1 小时前
Java——显示锁
java·开发语言
思麟呀1 小时前
在C++基础上理解Csharp-2
开发语言·jvm·c++·c#
桀人1 小时前
类和对象——上篇
开发语言·c++
ZC跨境爬虫1 小时前
跟着 MDN 学 HTML day_57:(HTML 表格进阶特性与无障碍实践)
java·前端·javascript·ui·html·音视频
zzzsde1 小时前
【Linux】线程概念与控制(3):线程ID&&C++封装线程
linux·运维·服务器·开发语言·算法
消失的旧时光-19431 小时前
C 语言如何实现“面向对象”?—— 从 struct + 函数指针,到 Linux 内核设计思想
linux·c语言·开发语言
鱼鳞_1 小时前
苍穹外卖-Day01(开发环境搭建)
java·spring boot·spring·maven
小短腿的代码世界2 小时前
Qt时间日期处理与QTimer高级应用:从毫秒级精度到跨平台定时器的完整架构解析
开发语言·qt·架构