遵守包含 class 名称的变量的 DRY 原则
respecting the DRY principle for variable containing the class name
如何设置包含 class 名称的变量,例如 android.util.Log
中的 TAG
,同时尊重 Dont-Repeat-Yourself?
这些是一些可能性:
在Google代码中,经常用like
public class Classname {
public final String TAG = "Classname";
它重复了 class 名称,并且在 AndroidStudio 中没有正确重构重命名(没有 String
是)。
然后,有一个动态变体
public class Classname {
public final String TAG = getClass().getName();
不重复类名,看起来更好,但可读性较差。
或者,您可以制作 TAG static
(这可能是过早的优化)。除了上面的官方版本,你可以在代码中获取名称,如
public class Classname {
public final static String TAG
= new Object() { }.getClass().getEnclosingClass().getName();
可读性较差,并且确实存在继承问题(静态)。
这方面的最佳做法是什么?
还有比1-3更好的方法吗? (或者这是一种错误的做法?)
我过去使用过动态方法:
public class Classname {
public final String TAG = getClass().getName();
不是不可读,而是自成体系。
对于更复杂的 DRY-ness 情况,始终可以创建自己的注释,然后
- 使用两步编译过程首先生成非 DRY 源,然后将它们编译成非 DRY .class 文件。
- 在程序的初始化步骤中使用注解在 运行 时间填充非 DRY 部分,然后再 运行 依赖于这些部分的任何逻辑。
使用第二种方法,你可以得到类似
的东西
@ReplaceWithClassName("TAG")
public class Classname {
public final String TAG;
然后你将遍历所有用 @ReplaceWithClassName
注释的 classes 作为初始化步骤填充空白(更多关于遍历带注释的 classes here; more on changing a final String here ).
注解、内省和代码生成提供了极大的灵活性和强大的功能。因此,如果您使用它们,请明智地使用它们。对于这种特殊情况,"dynamic approach" 更具可读性。
动态检索 class 名称
@JeffMiller 在他的 sormula 项目的 ClassLogger class 中给出了示例。在classLogger
中,他使用
StackTraceElement[] stes = new Throwable().getStackTrace();
int e = stes.length - 1;
for (int i = 0; i < e; ++i) {
if (stes[i].getClassName().equals(classLoggerClassName)) {
// next on stack is the class that created me
log = LoggerFactory.getLogger(stes[i + 1].getClassName());
break;
}
}
获取来电者的 class 姓名。
使用 class 获取其名称
@FlorentBayle 在评论中说
public final static String TAG = Classname.class.getName();
应该正确重构。 (并且比上面的变体 3 更具可读性)。
这也是 SLF4J 等第三方日志记录框架使用的方法。它通过
初始化
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
如何设置包含 class 名称的变量,例如 android.util.Log
中的 TAG
,同时尊重 Dont-Repeat-Yourself?
这些是一些可能性:
在Google代码中,经常用like
public class Classname {
public final String TAG = "Classname";
它重复了 class 名称,并且在 AndroidStudio 中没有正确重构重命名(没有 String
是)。
然后,有一个动态变体
public class Classname {
public final String TAG = getClass().getName();
不重复类名,看起来更好,但可读性较差。
或者,您可以制作 TAG static
(这可能是过早的优化)。除了上面的官方版本,你可以在代码中获取名称,如
public class Classname {
public final static String TAG
= new Object() { }.getClass().getEnclosingClass().getName();
可读性较差,并且确实存在继承问题(静态)。
这方面的最佳做法是什么?
还有比1-3更好的方法吗? (或者这是一种错误的做法?)
我过去使用过动态方法:
public class Classname {
public final String TAG = getClass().getName();
不是不可读,而是自成体系。
对于更复杂的 DRY-ness 情况,始终可以创建自己的注释,然后
- 使用两步编译过程首先生成非 DRY 源,然后将它们编译成非 DRY .class 文件。
- 在程序的初始化步骤中使用注解在 运行 时间填充非 DRY 部分,然后再 运行 依赖于这些部分的任何逻辑。
使用第二种方法,你可以得到类似
的东西@ReplaceWithClassName("TAG")
public class Classname {
public final String TAG;
然后你将遍历所有用 @ReplaceWithClassName
注释的 classes 作为初始化步骤填充空白(更多关于遍历带注释的 classes here; more on changing a final String here ).
注解、内省和代码生成提供了极大的灵活性和强大的功能。因此,如果您使用它们,请明智地使用它们。对于这种特殊情况,"dynamic approach" 更具可读性。
动态检索 class 名称
@JeffMiller 在他的 sormula 项目的 ClassLogger class 中给出了示例。在classLogger
中,他使用
StackTraceElement[] stes = new Throwable().getStackTrace();
int e = stes.length - 1;
for (int i = 0; i < e; ++i) {
if (stes[i].getClassName().equals(classLoggerClassName)) {
// next on stack is the class that created me
log = LoggerFactory.getLogger(stes[i + 1].getClassName());
break;
}
}
获取来电者的 class 姓名。
使用 class 获取其名称
@FlorentBayle 在评论中说
public final static String TAG = Classname.class.getName();
应该正确重构。 (并且比上面的变体 3 更具可读性)。
这也是 SLF4J 等第三方日志记录框架使用的方法。它通过
初始化Logger logger = LoggerFactory.getLogger(HelloWorld.class);