建议分开存放,原因如下:
一、为什么不建议放一起?
❌ 错误示例:混在一起
java
public class GlobalData {
// 可变数据(会修改)
private String userToken;
private int userId;
private boolean isLoggedIn;
private Map<String, Object> cache = new HashMap<>();
// 固定数据(不会修改)
public static final String API_BASE_URL = "https://api.example.com";
public static final int CONNECT_TIMEOUT = 30000;
public static final String APP_NAME = "MyApp";
// 混乱!不知道哪些能改哪些不能改
}
问题:
- 新人不知道哪些是常量,可能会误修改
- 文件职责不单一
- 代码混乱,难以维护
二、推荐的分离方案
✅ 方案1:按类型分离(推荐)
java
// 1. 可变数据用单例
public class UserSession {
private static final UserSession INSTANCE = new UserSession();
private String userToken;
private int userId;
private boolean isLoggedIn;
private Map<String, Object> cache = new HashMap<>();
private UserSession() {}
public static UserSession getInstance() { return INSTANCE; }
// getter/setter...
}
// 2. 固定数据用常量类
public final class AppConstants {
private AppConstants() {} // 防止实例化
// API相关
public static final String API_BASE_URL = "https://api.example.com";
public static final int CONNECT_TIMEOUT = 30000;
public static final int READ_TIMEOUT = 30000;
// 应用配置
public static final String APP_NAME = "MyApp";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0.0";
// SharedPreferences Key
public static final String SP_USER_TOKEN = "user_token";
public static final String SP_IS_LOGIN = "is_login";
// Intent Extra Key
public static final String EXTRA_USER_ID = "user_id";
public static final String EXTRA_PRODUCT_ID = "product_id";
}
// 使用
UserSession.getInstance().setUserToken("token"); // 修改
INSTANCE
String url = AppConstants.API_BASE_URL; // 读取常量
✅ 方案2:Kotlin方式(更优雅)
kotlin
// 可变数据用 object(单例)
object UserSession {
var userToken: String = ""
var userId: Int = 0
var isLoggedIn: Boolean = false
val cache = mutableMapOf<String, Any>()
}
// 固定数据用 object 或单独文件
object ApiConfig {
const val BASE_URL = "https://api.example.com"
const val CONNECT_TIMEOUT = 30000
}
// 或者用文件顶层的 const(推荐)
// Constants.kt
const val API_BASE_URL = "https://api.example.com"
const val CONNECT_TIMEOUT = 30000
// 使用
UserSession.userToken = "token" // 修改
val url = API_BASE_URL // 读取常量
✅ 方案3:按功能模块分离(大型项目)
java
// 按模块分离,更清晰
com.yourapp/
├── data/
│ ├── session/
│ │ └── UserSession.java // 用户会话数据
│ ├── config/
│ │ └── AppConfig.java // 应用配置
│ └── constants/
│ ├── ApiConstants.java // API常量
│ ├── IntentConstants.java // Intent常量
│ └── SharedPrefsKeys.java // SP键名
java
// ApiConstants.java
public final class ApiConstants {
private ApiConstants() {}
public static final String BASE_URL = "https://api.example.com";
public static final String LOGIN_URL = BASE_URL + "/login";
public static final String USER_INFO_URL = BASE_URL + "/user/info";
}
// IntentConstants.java
public final class IntentConstants {
private IntentConstants() {}
public static final String EXTRA_USER_ID = "user_id";
public static final String EXTRA_PRODUCT_ID = "product_id";
public static final String EXTRA_ORDER_ID = "order_id";
}
// UserSession.java(可变数据)
public class UserSession {
private static final UserSession INSTANCE = new UserSession();
private String userToken;
private UserInfo userInfo;
// ...
}
三、特殊情况:可以放一起的场景
场景1:非常小的工具类
java
// 如果只是几个紧密相关的常量,可以放一起
public class PreferenceKeys {
private PreferenceKeys() {}
// 这些都是常量,不涉及可变数据
public static final String KEY_USER_TOKEN = "user_token";
public static final String KEY_IS_LOGIN = "is_login";
public static final String KEY_THEME_MODE = "theme_mode";
}
场景2:配置类(固定配置)
java
// 全部是固定配置,没有可变数据
public class AppConfig {
private AppConfig() {}
// 这些都是固定值
public static final String API_URL = BuildConfig.API_URL;
public static final boolean DEBUG = BuildConfig.DEBUG;
public static final int MAX_CACHE_SIZE = 50;
}
四、写起来有点复杂?
java
// 饿汉式(最简单!)
public class UserManager {
// 就这一行!
public static final UserManager INSTANCE = new UserManager();
private UserManager() {} // 私有构造
public void doSomething() {}
}
// 使用
UserManager.INSTANCE.doSomething();
五、对比表格
| 特性 | 混在一起 | 分开放置 |
|---|---|---|
| 代码可读性 | ❌ 混乱 | ✅ 清晰 |
| 误修改风险 | ❌ 容易误改常量 | ✅ 常量不可修改 |
| 职责单一 | ❌ 违反单一职责 | ✅ 符合设计原则 |
| 团队协作 | ❌ 容易冲突 | ✅ 互不干扰 |
| 测试难度 | ❌ 难以Mock | ✅ 易于测试 |
| 维护成本 | ❌ 越来越高 | ✅ 长期稳定 |
六、最佳实践建议
1. 使用 Kotlin 的方式(最推荐)
kotlin
// 常量:单独文件或 companion object
object Api {
const val BASE_URL = "https://api.example.com"
}
// 可变数据:object 单例
object UserManager {
var token: String = ""
var userId: Int = 0
}
// 或者用 data class + StateFlow(更现代)
class UserRepository {
private val _userData = MutableStateFlow<UserData?>(null)
val userData = _userData.asStateFlow()
}
2. Java项目的标准结构
java
// Constants.java - 所有常量
public final class Constants {
private Constants() {}
public static final class Api {
public static final String BASE_URL = "https://api.example.com";
}
public static final class Intent {
public static final String EXTRA_USER_ID = "user_id";
}
}
// GlobalData.java - 只放可变数据
public class GlobalData {
private static final GlobalData INSTANCE = new GlobalData();
private String userToken;
// 只放会变的数据
}
3. 记住这个原则
- 固定的 → 常量类、枚举、配置文件
- 会变的 → 单例、ViewModel、Repository
- 不要混在一起!
七、总结
不要放同一文件!
- ✅ 固定数据 :放在
Constants.java或Config.java - ✅ 可变数据 :放在
UserSession.java或GlobalData.java(单例)
好处:
- 代码更清晰,职责分明
- 避免误修改常量
- 便于团队协作
- 更容易测试和维护
简单记忆: 常量放左边,变量放右边,各放各的文件!