gpt4 book ai didi

java - 当条件诊断关闭时,在 Java 中添加条件诊断是否可以实现零成本?

转载 作者:行者123 更新时间:2023-11-30 05:41:00 24 4
gpt4 key购买 nike

这实际上是一个关于 Java 的问题,而不是关于 C++ 的问题。

这个想法是您希望能够添加可以通过设置标志来打开和关闭的在线诊断。并且您希望在关闭标志时成本较低且接近或为零。

几年前,我在 C++ 中实现了一个名为“调试器”的类来执行此操作。该设计使用枚举作为标志名称,因此您可以获得可读、高效且类型安全的代码。用法如下所示。

enum DebugBits {
testCondition1,
testCondition2,
testCondition3
nTestConditions
}`
Debugger testDebug("testDebug", nTestConditions,
"condition1",
"condition2",
"condition3");

Critical::doStuff()
{
...
if (testDebug.on(testCondition2))
doSomethingSpecial();
...
}

这可以通过使用枚举值和内联方法索引的位轻松实现。它在大型实时系统中运行良好,并且在关闭调试时成本几乎为零。它是一个有值(value)的工具。

无论如何,回到问题。今天,出于个人原因,我正在考虑在 Java 中做同样的事情,但考虑到你不能子类化枚举,但使用它们会很好,保持声明清晰和在代码简介。

所以这是一个有效的实现,并且有点高效。问题是,

  • 实现能否更加高效?
  • 同时代码中的用法能否保持清晰?

我怀疑有更好的 Java 程序员可能对如何做到这一点有更好的想法。在顶部添加一个包,这应该可以编译并运行。底部还有一个类来演示用法。请注意,其中应该包含更多内容,但这是有趣的核心部分。嗯...对我来说。

import java.util.BitSet;
import java.util.EnumSet;
import java.util.Vector;

public class Debugger {
private final EnumSet mEnumSet;
private final BitSet mBits;
private final Vector<String> mNames;

public Debugger(EnumSet es) {
mEnumSet = es;
mBits = new BitSet(es.size());
mNames = new Vector<>();
for (Object i : mEnumSet)
mNames.add(i.toString());
}

public void set(int bit) {
mBits.set(bit);
}

public void set(String bitName) {
int bit = mNames.indexOf(bitName);
if (bit >= 0)
mBits.set(bit);
}

public boolean on(int bit) {
return mBits.get(bit);
}

public boolean on(Object arg) {
if (arg.getClass() == Enum.class) {
int bit = ((Enum)arg).ordinal();
return mBits.get(bit);
}
return false;
}

public boolean on(String bitName) {
int bit = mNames.indexOf(bitName);
return bit >= 0 && mBits.get(bit);
}
}

class SampleUsage {
static class Debug extends Debugger {
enum Bits {
zero, one, two, three;
public static final EnumSet<Bits> bits = EnumSet.allOf(Bits.class);
}
public Debug() {
super(Bits.bits);
}
}
public static final Debug debug = new Debug();

public SampleUsage() {}

void doStuff() {
if (debug.on(Debug.Bits.three))
showDebugInfo();
if (debug.on("three"))
showDebugInfo();
}

private void showDebugInfo() {}
}

最佳答案

我认为你错过了 EnumSet<> 的要点。 EnumSet<>是类型安全的高效调试标志集。

enum Debug {
FLAG0, FLAG1, FLAG2;
}

EnumSet<Debug> debug = EnumSet.noneOf(Debug.class);

debug.add(Debug.FLAG0);

if (debug.contains(Debug.FLAG0)) {
showDebugInfo0(); // Will be executed.
}

if (debug.contains(Debug.FLAG1)) {
showDebugInfo1(); // Will not be executed because FLAG1 was not added to the EnumSet.
}

无需翻译 enum值转换为序数,并将该序数添加到 BitSetEnumSet<>已经使用类似 BitSet 的东西实现了(除了 EnumSet<> 具有固定大小,基于 Enum 中标识符的数量,因此不能扩展到任意长度)。

如果您想测试是否按名称设置了标志,可以使用 Enum.valueOf()将名称转换为正确的 Enum ,并测试 EnumSet<> 是否包含该内容。

if (debug.contains(Enum.valueOf(Debug.class, "FLAG2")) {
showDebugInfo2(); // Also not executed, because FLAG2 was not added to the EnumSet.
}

再说一次,不需要 Vector<String>包含所有 Enum名称,您必须找到 .indexOf()Enum内置了该方法。 Vector<>无论如何,这不是一个有效的选择,因为 Vector<>操作自动 synchronized ,因此比同等的 ArrayList<> 稍慢.

注意:细微差别:.indexOf()未找到时返回-1; Enum.valueOf()将筹集 IllegalArgumentException如果您给它一个未知的标识符名称。

<小时/>

假设你想要.on() ,不是.contains() ,并且您希望在代码中按名称使用更简单的测试标志,我们需要包装 EnumSet<>在另一个类(class)。这个Debug类可能看起来像:

class Debug<T extends Enum<T>> {
private final Class<T> enum_class;
private final EnumSet<T> flags;

public Debug(Class<T> enum_class) {
this.enum_class = enum_class;
flags = EnumSet.noneOf(enum_class);
}

public void set(T flag) {
flags.add(flag);
}

public boolean on(T flag) {
returns flags.contains(flag);
}

public void set(String flag_name) {
flags.add(Enum.valueOf(enum_class, flag_name));
}

public boolean on(String flag_name) {
return flags.contains(Enum.valueOf(enum_class, flag_name));
}
}

关于java - 当条件诊断关闭时,在 Java 中添加条件诊断是否可以实现零成本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55671837/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com