如果您不想使用Java的东西,那么一个好的首个开始是调用一种方法(如果您真的需要它,请静态)来获取这些字符串;您不想写regiei18n.key_action_execute,您想编写regiei18n.getKeyiationActionExecute() ,甚至regiei18n.key_key_action_eaction_execute()(请注意末尾的括号)。您可以使用代码 - 基因创建这些方法。现在,您可以灵活地编写您在其中的感觉,而JVM将永远不会内联,或者以其他方式消除了这样的电话。如果以后您决定要该方法返回其他内容,并且要通过重新编译 Just regiei18n进行部署,那么您可以。
当然,您只是重新发明车轮,但这摆脱了S3252试图解决的主要问题。
This is steering dangerously close to 'opinion' which is beyond the scope of SO. Hence, not much opinion in this answer - just the objective basis on which S3252 is based.
Java is generally called 'Object Oriented' and as a consequence, most of its concepts are explained in terms of OO - and presumably your average java coder's instincts lie in the OO direction.
That's a problem in this case: static stuff does not "do" OO. AT ALL. - for example, dynamic dispatch (where if you call someAnimalRef.makeNoise() will actually call the Dog class's makeNoise() method if the ref turns out to be referencing an instance of Dog, even though the variable someAnimalRef is typed Animal) - does not apply to static at all.
In other words, given that this is static stuff, javac decides which constant to use (and for an encore, if said constant is Compile Time Constant - i.e. a string or number literal or could have been derived using only baked-in math (no libraries) that involves only literals – then any refs to this variable are straight up replaced with the constant directly).
This could be confusing. The way you wrote it, you're still getting 'inheritance' of sorts - but it's compile time inheritance. Specifically, if you have (store these 3 in separate files):
interface CommonI18n {
String KEY_ACTION_EXECUTE = "Execute";
}
interface RegieI18N extends CommonI18n {
}
class Test {
public static void main(String[] args) {
System.out.println(RegieI18N.KEY_ACTION_EXECUTE);
}
}
and run:
javac *.java; java Test
It prints Execute, obviously. If you then edit RegieI18N.java to this and recompile just it:
interface RegieI18N extends CommonI18n {
String KEY_ACTION_EXECUTE = "Uitvoeren";
}
// and then on the command line:
javac RegieI18N.java
java Test
It still prints Execute, even though your intent was obviously that it should be printing Uitvoeren now. There are 2 separate reasons for this (and either one is sufficient): [A] Static stuff is resolved 100% by javac, so unless you're recompiling Test.java, it'll never work, and [B] constants like this are inlined.
That's what the underlying idea behind the warning: That this is confusing, and even if not, that this is hampering your future flexibility. You cannot introduce/change any of the i18n stuff unless you recompile the entire application. Given that some 'incremental compilation' tools will not recompile Test if Test.class is newer than Test.java, that's quite a big deal.
So to avoid this?
Simple - don't use constants. Don't use static if you want the ability to 'override in a subtype'. Java has i18n stuff baked in, where you put the data in properties files which you can then ship together with your class files (inside jars, if you want). This interface based strategy seems to have essentially no upside (I guess technically its more performant, but I doubt you could ever measure it, and given that i18n kinda implies 'strings that are meant for human eyeballs', and 'meant for human eyeballs' kinda implies: The CPU is so not going to be the bottleneck, you can completely ignore it), the performance upside seems like a farcically crazy misunderstanding of perspective here. Worrying about performance for this is completely wrong. Most likely - there are exceptions to every rule, of course.
If somehow you don't want to use java's stuff, a good first start is to invoke a method (static if you really need it to be) to get these strings; you don't want to write RegieI18N.KEY_ACTION_EXECUTE, you want to write something like RegieI18N.getKeyActionExecute(), or even RegieI18n.KEY_ACTION_EXECUTE() (note the parentheses at the end there). You can use code-gen to create these methods if you must. You now have the flexibility to write whatever you feel like in these, and the JVM will never inline or otherwise just eliminate such a call. If later on you decide you want that method to return something else, and you want to deploy it by recompiling just RegieI18n, then now you can.
You're just reinventing wheels badly of course, but that gets rid of the primary concern that S3252 is trying to address.
发布评论
评论(1)
这是危险地转向“意见”,这超出了SO的范围。因此,在此答案中,意见不多 - 只是S3252所基于的客观基础。
Java通常称为“面向对象”,因此,其大多数概念都用OO来解释 - 大概是您的普通Java编码器的直觉在OO方向上。
在这种情况下,这是一个问题:
static
东西 不“做” oo。根本。事实证明,即使变量soseanimalref
键入Animal
) - 在全部。换句话说,鉴于这是静态的东西,
javac
决定要使用哪些常数(对于encore,如果上述常数为编译时间是常数 - 即字符串或数字字面或可以使用只有仅涉及文字的数学(无库) - 然后直接将其直接替换为常数)。这可能会令人困惑。以您的写作方式,您仍然会获得各种“继承” - 但这是编译时间的继承。具体来说,如果您有(将这3个存储在单独的文件中):
并运行:
它打印
执行
,显然。如果您然后编辑regiei18n.java
对此进行重新编译它:它 stly意图显然是现在应该打印
uitvoeren
。有两个单独的原因(这是足够的):[a]静态内容由javac
100%解析,因此,除非您要重新编译test.java
,它永远不会起作用,并且像这样的[b]常数被内衬。这就是警告背后的基本思想:这是令人困惑的,即使不是,这也阻碍了您未来的灵活性。您 除非您重新编译整个应用程序,否则更改/更改I18N的任何内容。鉴于,如果
test.class
比test.java
,则某些“增量编译”工具将不会重新编译测试,这很重要。所以避免这种情况?
简单 - 不要使用常数。如果您希望能够“覆盖子类型”,请勿使用
静态
。 Java将i18n的东西烤进去,在其中将数据放入属性文件中,然后将其与类文件一起运送(如果需要的话,可以在罐子内部)。这种基于接口的策略似乎基本上没有上涨(我想从技术上讲它的性能更高,但我怀疑您是否可以衡量它,并且鉴于I18N有点暗示着“针对人类眼球的字符串”,并且“为人类的眼球'' Kinda暗示:CPU是不可能是瓶颈,您可以完全忽略它),在这里,性能上升似乎是对观点的 farclactiand Carccarcy Craveant Craveance误解。担心性能是完全错误的。最有可能的 - 当然,每个规则都有例外。如果您不想使用Java的东西,那么一个好的首个开始是调用一种方法(如果您真的需要它,请静态)来获取这些字符串;您不想写
regiei18n.key_action_execute
,您想编写regiei18n.getKeyiationActionExecute()
,甚至regiei18n.key_key_action_eaction_execute()(请注意末尾的括号)。您可以使用代码 - 基因创建这些方法。现在,您可以灵活地编写您在其中的感觉,而JVM将永远不会内联,或者以其他方式消除了这样的电话。如果以后您决定要该方法返回其他内容,并且要通过重新编译 Just regiei18n进行部署,那么您可以。
当然,您只是重新发明车轮,但这摆脱了S3252试图解决的主要问题。
This is steering dangerously close to 'opinion' which is beyond the scope of SO. Hence, not much opinion in this answer - just the objective basis on which S3252 is based.
Java is generally called 'Object Oriented' and as a consequence, most of its concepts are explained in terms of OO - and presumably your average java coder's instincts lie in the OO direction.
That's a problem in this case:
static
stuff does not "do" OO. AT ALL. - for example, dynamic dispatch (where if you callsomeAnimalRef.makeNoise()
will actually call the Dog class'smakeNoise()
method if the ref turns out to be referencing an instance of Dog, even though the variablesomeAnimalRef
is typedAnimal
) - does not apply tostatic
at all.In other words, given that this is static stuff,
javac
decides which constant to use (and for an encore, if said constant is Compile Time Constant - i.e. a string or number literal or could have been derived using only baked-in math (no libraries) that involves only literals – then any refs to this variable are straight up replaced with the constant directly).This could be confusing. The way you wrote it, you're still getting 'inheritance' of sorts - but it's compile time inheritance. Specifically, if you have (store these 3 in separate files):
and run:
It prints
Execute
, obviously. If you then editRegieI18N.java
to this and recompile just it:It still prints
Execute
, even though your intent was obviously that it should be printingUitvoeren
now. There are 2 separate reasons for this (and either one is sufficient): [A] Static stuff is resolved 100% byjavac
, so unless you're recompilingTest.java
, it'll never work, and [B] constants like this are inlined.That's what the underlying idea behind the warning: That this is confusing, and even if not, that this is hampering your future flexibility. You cannot introduce/change any of the i18n stuff unless you recompile the entire application. Given that some 'incremental compilation' tools will not recompile Test if
Test.class
is newer thanTest.java
, that's quite a big deal.So to avoid this?
Simple - don't use constants. Don't use
static
if you want the ability to 'override in a subtype'. Java has i18n stuff baked in, where you put the data in properties files which you can then ship together with your class files (inside jars, if you want). This interface based strategy seems to have essentially no upside (I guess technically its more performant, but I doubt you could ever measure it, and given that i18n kinda implies 'strings that are meant for human eyeballs', and 'meant for human eyeballs' kinda implies: The CPU is so not going to be the bottleneck, you can completely ignore it), the performance upside seems like a farcically crazy misunderstanding of perspective here. Worrying about performance for this is completely wrong. Most likely - there are exceptions to every rule, of course.If somehow you don't want to use java's stuff, a good first start is to invoke a method (static if you really need it to be) to get these strings; you don't want to write
RegieI18N.KEY_ACTION_EXECUTE
, you want to write something likeRegieI18N.getKeyActionExecute()
, or evenRegieI18n.KEY_ACTION_EXECUTE()
(note the parentheses at the end there). You can use code-gen to create these methods if you must. You now have the flexibility to write whatever you feel like in these, and the JVM will never inline or otherwise just eliminate such a call. If later on you decide you want that method to return something else, and you want to deploy it by recompiling just RegieI18n, then now you can.You're just reinventing wheels badly of course, but that gets rid of the primary concern that S3252 is trying to address.