接口(interface)中的常量和 类(class)中的常量的区别

接口(interface)中的常量类(class)中的常量 的区别。

1、定义方式

1.1. 接口中的常量(interface constant)

ini 复制代码
public interface Config {
    // 不需要显式写 public static final
    String NAME = "A**";
    int MAX_COUNT = 100;
}

接口中定义的变量,默认就是 public static final,即使你不写,编译器也会自动加上。

  • public:公开访问
  • static:属于接口本身,不依赖实例
  • final:不可修改

1.2. 类中的常量(class constant)

arduino 复制代码
public class Config {
    // 必须显式声明 static final
    public static final String NAME = "A**";
    public static final int MAX_COUNT = 100;
}

类中必须显式写出 static final,否则就不是常量。

2、核心区别对比

特性 接口中的常量 类中的常量
修饰符是否可选 ✅ 隐式 public static final,可不写 ❌ 必须显式写 static final
访问方式 InterfaceName.CONSTANT ClassName.CONSTANT
是否可以修改 final,不可变 final,不可变
存储位置 方法区(元数据) 方法区(类静态变量)
继承行为 实现类自动继承常量 子类可以继承 public/protected
初始化时机 接口加载时初始化 类加载时初始化
性能 几乎无差别 几乎无差别
使用场景 定义公共配置、协议常量 定义类相关的常量、配置

3、代码示例

示例 1:接口常量的继承

typescript 复制代码
public interface AppConfig {
    String DOMAIN = "XX";
    String TOKEN = "....";
}

public class LoginService implements AppConfig {
    public void connect() {
        System.out.println("域名: " + DOMAIN); // 直接使用接口常量
    }
}

LoginService 虽然没有实现方法,但可以直接使用 DOMAINTOKEN

示例 2:类常量的继承

scala 复制代码
public class AppConfig {
    public static final String ENV = "prod";
}
public class DatabaseConfig extends AppConfig {
    public void printEnv() {
        System.out.println("环境: " + ENV); // 继承父类常量
    }
}

类通过继承获得常量。

4、注意:

1. 接口常量是"隐式 public static final"

ini 复制代码
interface BadExample {
    final String NAME = "Alice";        // ❌ 冗余,final 可省略
    static int COUNT = 10;              // ❌ 冗余
    // private String SECRET = "...";   // ❌ 编译错误!接口常量必须是 public
}

2. 接口不能有"实例常量"

  • 不能有实例变量和实例常量(包括常量)
  • 所有字段必须是 public static final(即:类常量)
  • 接口不能被实例化,所以"实例"相关的概念都不存在
java 复制代码
interface BadExample {
    final String name = "Alice"; // ✅ 可以,但它是 static final(接口常量)
    
    // String instanceValue; // ❌ 错误!接口不能有实例变量
}

3. 接口常量会类常量必须在声明时初始化(因为final修饰)

ini 复制代码
interface Config {
    // String NAME; // ❌ 编译错误!必须赋值
    String NAME = "Alice"; // ✅
}

5、使用建议

场景 推荐方式
定义一组公共配置(如 API 地址、状态码) ✅ 使用 interface 常量(简洁)
常量与某个类强相关(如 Math.PI ✅ 使用 class 常量
常量需要封装逻辑(如通过方法计算) ✅ 使用 class + 私有构造

6、什么是"实例常量"?

"实例常量"指的是:

  • 使用 final 修饰的成员变量
  • 属于对象实例(而不是类)
  • 每个对象可以有不同的值
  • 一旦创建后不可修改

示例:定义实例常量

arduino 复制代码
public class Person {
    // 实例常量:每个 Person 对象都有自己的 name 和 id
    private final String name;
    private final long id;

    // 构造函数中初始化
    public Person(String name, long id) {
        this.name = name;
        this.id = id;
    }

    // 只有 getter,没有 setter(因为是常量)
    public String getName() {
        return name;
    }

    public long getId() {
        return id;
    }
}

使用:

ini 复制代码
Person p1 = new Person("Alice", 1L);
Person p2 = new Person("Bob", 2L);

// p1.name = "Charlie"; // ❌ 编译错误!不能修改 final 变量

nameid 就是典型的"实例常量"------每个对象有自己的值,且创建后不可变。

相关推荐
D***77652 分钟前
适用于IntelliJ IDEA 2024.1.2部署Tomcat的完整方法,以及笔者踩的坑,避免高血压,保姆级教程
java·tomcat·intellij-idea
豆浆whisky4 分钟前
Go并发模式选择指南:找到最适合你项目的并发方案|Go语言进阶(19)
开发语言·后端·golang
20岁30年经验的码农5 分钟前
Spring Security 6.x 安全实践指南
java
胖咕噜的稞达鸭1 小时前
自定义shell命令行解释器自制
java·开发语言
q***33374 小时前
oracle 12c查看执行过的sql及当前正在执行的sql
java·sql·oracle
Y***h1877 小时前
第二章 Spring中的Bean
java·后端·spring
8***29317 小时前
解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域
java·前端·spring
CoderYanger8 小时前
优选算法-栈:67.基本计算器Ⅱ
java·开发语言·算法·leetcode·职场和发展·1024程序员节
q***06298 小时前
Tomcat的升级
java·tomcat
稚辉君.MCA_P8_Java8 小时前
DeepSeek 插入排序
linux·后端·算法·架构·排序算法