java枚举有啥不好

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java枚举有啥不好相关的知识,希望对你有一定的参考价值。

我在java webapp项目里面使用枚举,但是主管总是对我使用枚举有意见,我问原因他说没有看到那个书上用枚举,他说如果看到那本书上有写使用枚举的以后就不说我了,那我就觉得奇怪了,java枚举有哪些缺点,为什么没有普及。网络上没有太多说java有哪些优缺点的

没有他说的那么绝对。没有不好用的,只有不适合用、不擅长用的。
在webapp里面,用枚举不如用xml或properties或数据字典,因为维护容易,用枚举得改类,再编译,再替换到服务器上,而用后面的直接修改服务器文件或者在系统上配置就OK了
参考技术A 看看枚举的写法吧你们。
需要get set方法支持的类型
就会有实例化风险
一实例化相对就消耗内存
谁爱用用 反正我不用
一群菜鸟 只会跟风不会思考

35岁淘汰的就是你们
参考技术B 枚举相对于静态常量需要更多的内存 参考技术C 枚举的内存开销比较大吧 参考技术D 确实莫名其妙 。我也想知道。估计是那人书看的比较少吧。呵呵

Lazy I/O 有啥不好?

【中文标题】Lazy I/O 有啥不好?【英文标题】:What's so bad about Lazy I/O?Lazy I/O 有什么不好? 【发布时间】:2011-08-19 01:22:18 【问题描述】:

我通常听说生产代码应避免使用延迟 I/O。我的问题是,为什么?除了玩弄之外,还可以使用 Lazy I/O 吗?是什么让替代品(例如枚举器)更好?

【问题讨论】:

【参考方案1】:

Lazy IO 的问题是,释放您获得的任何资源在某种程度上是不可预测的,因为它取决于您的程序如何使用数据——它的“需求模式”。一旦您的程序删除了对该资源的最后一个引用,GC 最终将运行并释放该资源。

惰性流是一种非常方便编程的风格。这就是为什么 shell 管道如此有趣和流行的原因。

但是,如果资源受到限制(如在高性能场景中,或希望扩展到机器极限的生产环境中),则依靠 GC 进行清理可能是一个不充分的保证。

有时您必须急切地释放资源,以提高可扩展性。

那么有哪些惰性 IO 替代方案并不意味着放弃增量处理(这反过来又会消耗太多资源)?嗯,我们有基于 foldl 的处理,也称为迭代器或枚举器,由 Oleg Kiselyov in the late 2000s 引入,并被许多基于网络的项目推广。

我们不是将数据作为惰性流或一个大批量处理,而是通过基于块的严格处理进行抽象,并保证在读取最后一个块后资源的最终确定。这就是基于迭代的编程的精髓,它提供了非常好的资源约束。

基于迭代的 IO 的缺点是它有一个有点笨拙的编程模型(大致类似于基于事件的编程,而不是基于线程的控制)。在任何编程语言中,这绝对是一种先进的技术。而对于绝大多数编程问题,惰性IO完全可以满足。但是,如果您要打开许多文件,或者在许多套接字上进行通信,或者以其他方式同时使用许多资源,那么迭代器(或枚举器)方法可能是有意义的。

【讨论】:

因为我刚刚从关于惰性 I/O 的讨论中关注到这个老问题的链接,所以我想我应该添加一个注释,从那时起,迭代器的大部分尴尬已经被新的pipes 和 conduit 等流媒体库。【参考方案2】:

Dons 提供了一个很好的答案,但他忽略了(对我而言)迭代器最引人注目的特性之一:它们使空间管理的推理变得更容易,因为必须明确保留旧数据。考虑:

average :: [Float] -> Float
average xs = sum xs / length xs

这是众所周知的空间泄漏,因为必须将整个列表 xs 保留在内存中才能计算 sumlength。通过创建折叠可以成为高效的消费者:

average2 :: [Float] -> Float
average2 xs = uncurry (/) <$> foldl (\(sumT, n) x -> (sumT+x, n+1)) (0,0) xs
-- N.B. this will build up thunks as written, use a strict pair and foldl'

但是对于每个流处理器都必须这样做有点不方便。有一些概括 (Conal Elliott - Beautiful Fold Zipping),但它们似乎没有流行起来。但是,迭代器可以为您提供类似级别的表达。

aveIter = uncurry (/) <$> I.zip I.sum I.length

这不如折叠有效,因为列表仍然会迭代多次,但是它是按块收集的,因此可以有效地对旧数据进行垃圾收集。为了破坏该属性,有必要显式保留整个输入,例如使用 stream2list:

badAveIter = (\xs -> sum xs / length xs) <$> I.stream2list

迭代器作为编程模型的状态是一项正在进行的工作,但它比一年前要好得多。我们正在了解哪些组合器有用(例如zipbreakEenumWith),哪些不太有用,结果内置的迭代器和组合器不断提供更多的表现力。

也就是说,Dons 是正确的,他们是一种先进的技术;我当然不会对每个 I/O 问题都使用它们。

【讨论】:

【参考方案3】:

我一直在生产代码中使用惰性 I/O。就像唐提到的那样,这只是在某些情况下才会出现的问题。但是只读取几个文件就可以了。

【讨论】:

我也使用惰性 I/O。当我想要更多地控制资源管理时,我会求助于迭代器。【参考方案4】:

更新: 最近在 haskell-cafe Oleg Kiseljov showed 上,unsafeInterleaveST(用于在 ST monad 中实现惰性 IO)非常不安全 - 它破坏了等式推理。他表明它允许构造bad_ctx :: ((Bool,Bool) -&gt; Bool) -&gt; Bool 这样

> bad_ctx (\(x,y) -> x == y)
True
> bad_ctx (\(x,y) -> y == x)
False

即使== 是可交换的。


惰性 IO 的另一个问题:实际的 IO 操作可以推迟到为时已晚,例如在文件关闭之后。引用Haskell Wiki - Problems with lazy IO:

例如,一个常见的初学者错误是在一个文件读完之前关闭它:

wrong = do
    fileData <- withFile "test.txt" ReadMode hGetContents
    putStr fileData

问题是 withFile 在强制 fileData 之前关闭句柄。正确的做法是把所有的代码都传给withFile:

right = withFile "test.txt" ReadMode $ \handle -> do
    fileData <- hGetContents handle
    putStr fileData

这里,数据在 withFile 完成之前被消费。

这通常是意料之外且容易犯的错误。


另请参阅:Three examples of problems with Lazy I/O。

【讨论】:

实际上将hGetContentswithFile 结合起来是没有意义的,因为前者将句柄置于“伪关闭”状态并会(懒惰地)为您处理关闭,因此代码完全等同于@ 987654332@,甚至没有hCloseopenFile。这基本上就是惰性 I/O 。如果你不使用readFilegetContentshGetContents,你就没有使用惰性 I/O。例如line &lt;- withFile "test.txt" ReadMode hGetLine 工作正常。 @Dag:虽然hGetContents 会为您处理关闭文件,但也可以自己“提前”关闭它,这有助于确保资源以可预测的方式释放。【参考方案5】:

到目前为止还没有提到惰性 IO 的另一个问题是它具有令人惊讶的行为。在一个普通的 Haskell 程序中,有时很难预测程序的每个部分何时被评估,但幸运的是,由于纯度,除非你有性能问题,否则它真的无关紧要。当引入惰性 IO 时,代码的评估顺序实际上会影响其含义,因此您习惯认为无害的更改可能会给您带来真正的问题。

例如,这里有一个关于代码的问题,看起来很合理,但由于延迟 IO 而变得更加混乱:withFile vs. openFile

这些问题并不总是致命的,但这是另外一回事,而且我个人会避免懒惰的 IO,除非预先完成所有工作存在真正的问题。

【讨论】:

以上是关于java枚举有啥不好的主要内容,如果未能解决你的问题,请参考以下文章

java中的enum有啥用呢?

JAVA中枚举是啥意思,怎么用

java 为啥枚举能不用最好不要用呢?有啥问题吗

请问java枚举的用法都有哪些。

java的enum到底有啥用?

java枚举与.net中的枚举区别