UserManager
类中的以下方法:
public boolean isUserAGoat()
Used to determine whether the user making this call is subject to teleportations.
Returns whether the user making this call is a goat.
这应该如何使用?何时使用?
UserManager
类中的以下方法:
public boolean isUserAGoat()
Used to determine whether the user making this call is subject to teleportations.
Returns whether the user making this call is a goat.
这应该如何使用?何时使用?
从 Android R 开始,该方法始终返回 false。Google 表示这样做是为了"保护山羊隐私"。
/**
* Used to determine whether the user making this call is subject to
* teleportations.
*
* <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
* now automatically identify goats using advanced goat recognition technology.</p>
*
* <p>As of {@link android.os.Build.VERSION_CODES#R}, this method always returns
* {@code false} in order to protect goat privacy.</p>
*
* @return Returns whether the user making this call is a goat.
*/
public boolean isUserAGoat() {
if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R) {
return false;
}
return mContext.getPackageManager()
.isPackageAvailable("com.coffeestainstudios.goatsimulator");
}
根据他们的source,在API 21之前,使用的方法是返回false
。
/**
* Used to determine whether the user making this call is subject to
* teleportations.
* @return whether the user making this call is a goat
*/
public boolean isUserAGoat() {
return false;
}
看起来这个方法对我们开发者来说没有实际用处。有人之前说过它可能是一个彩蛋。
在API 21中,该实现已更改为检查是否安装了包名为com.coffeestainstudios.goatsimulator
的应用程序。
/**
* Used to determine whether the user making this call is subject to
* teleportations.
*
* <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
* now automatically identify goats using advanced goat recognition technology.</p>
*
* @return Returns true if the user making this call is a goat.
*/
public boolean isUserAGoat() {
return mContext.getPackageManager()
.isPackageAvailable("com.coffeestainstudios.goatsimulator");
}
这里是source和change。
我不知道这是否是“官方”用例,但以下代码在Java中会产生警告(如果与return
语句混合使用,则可能会导致编译错误,从而导致无法访问的代码):
我不确定这是否是“官方”用例,但以下代码在Java中会产生警告(如果与return
语句混合使用,则可能会导致编译错误,从而导致无法访问的代码):
while (1 == 2) { // Note that "if" is treated differently
System.out.println("Unreachable code");
}
然而,这是合法的:
while (isUserAGoat()) {
System.out.println("Unreachable but determined at runtime, not at compile time");
}
因此我经常会编写一个愚蠢的实用方法来快速虚拟出一个代码块,以便在完成调试后找到所有对它的调用,只要实现不改变,就可以用于这个目的。
JLS 指出 if (false)
不会触发“无法访问的代码”错误,原因是这会破坏对调试标志的支持,也就是说基本上是这种用例(参考 @auselen)。 (例如,static final boolean DEBUG = false;
)。
我将 while
替换为 if
,从而产生了一个更加晦涩的用例。我认为你可以利用这种行为使你的 IDE(如 Eclipse)出现问题,但是这个编辑已经是未来的 4 年了,我没有 Eclipse 环境可以测试。
if(false){...}
编译得很好(使用OpenJDK javac 1.6和1.7)。 - josefx这似乎是谷歌内部的一个笑话。它还出现在 Google Chrome 任务管理器中。 它没有任何目的,只是一些工程师觉得很有趣。如果您愿意,这本身就是一个目的。
甚至有一个关于 teleported goats太多 的巨大的Chromium bug报告。
下面这段Chromium 源代码片段是从HN的评论中盗取的。
int TaskManagerModel::GetGoatsTeleported(int index) const {
int seed = goat_salt_ * (index + 1);
return (seed >> 16) & 255;
}
补充 @djechlin 的回答(顺便说一句,很好的回答!),这个函数调用还可以被用作虚拟代码来在IDE中保持断点,当你想要在某个特定迭代或特定递归调用中停止时。例如:
isUserAGoat()
可以替代一个虚拟变量声明,在IDE中显示为警告信息,而在 Eclipse 中特别的情况下,它会堵塞断点标记,使其难以启用/禁用。如果该方法被用作惯例,所有调用都可以在提交阶段之后通过某些脚本进行过滤。
谷歌的员工是重度的 Eclipse 用户(他们提供了几个作为 Eclipse 插件的项目:Android SDK、GAE 等等),所以 @djechlin 的答案和这个补充答案对我来说很有意义。
在每个Android版本中都有一个有趣的命名方法/常量/其他。
我唯一看到的实际用途是在最后通唤的Google I/O比赛中,他们要求参赛者猜测特定版本的用途,以确定是否阅读了每个发布版的API差异报告。比赛还包括编程问题,但通常先有一些可以自动评分的琐事,以便将提交数量减少到较少的合理数量,这样更容易检查。
自 API 21(即 Android 5.0/Lollipop SDK 的第一个版本)起,此代码可以检测Goat Simulator 应用是否已安装:
/**
* Used to determine whether the user making this call is subject to
* teleportations.
*
* <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
* now automatically identify goats using advanced goat recognition technology.</p>
*
* @return Returns true if the user making this call is a goat.
*/
public boolean isUserAGoat() {
return mContext.getPackageManager()
.isPackageAvailable("com.coffeestainstudios.goatsimulator");
}
这应该可以清楚地表明,djechlin的建议将其用作无警告的if (false)
是一种潜在的灾难性策略。现在对于每个设备以前返回false
的东西现在返回了一个看似随机的值:如果这被深深地埋在你的代码中,可能需要很长时间才能弄清楚你的新错误来自哪里。
底线:如果你不能控制方法的实现并决定将其用于API文档中未说明的其他目的,那么你会遇到问题。
if(false)
呢?得了吧,如果你的代码看起来像这样,那么实现更改只是你面临问题中最不重要的一个。 - djechlin谷歌非常喜欢山羊和基于山羊的彩蛋。甚至有之前在Stack Overflow上发布的帖子提到过这一点。
正如之前的帖子中提到的那样,它也存在于Chrome任务管理器中(它最早出现在2009年):
<message name="IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN" desc="The goats teleported column">
Goats Teleported
</message>
然后在Windows、Linux和Mac版本的Chrome早期2010年)。"传送山羊"的数量实际上是随机:
int TaskManagerModel::GetGoatsTeleported(int index) const {
int seed = goat_salt_ * (index + 1);
return (seed >> 16) & 255;
}
谷歌对山羊的其他参考资料包括:
据我所知,最早将山羊和谷歌联系起来的是原始的“与山羊一起修剪草坪”博客文章。
我们可以安全地假设这只是一个复活节彩蛋,没有实际用途,除了返回false
。
有一个类似的调用,isUserAMonkey()
,如果正在使用MonkeyRunner 工具,则返回true。SDK的解释和这个一样奇怪。
public static boolean isUserAMonkey(){}
如果用户界面当前被猴子搞乱,则返回true
。
这里是来源。
我认为这是为了预测一个名字中带有“山羊”的新SDK工具的到来,并且实际上将对该工具的存在进行功能测试。
ActivityManager
报告它是否被monkey
UI压力测试工具调用,但我从未确认过。 - CtrlF有趣的复活节彩蛋。
在Chrome的Ubuntu版本中,在任务管理器(shift+esc)中,用右键单击可以添加一个科幻栏目,它在意大利版中被称为“Capre Teletrasportate”(瞬间传送的山羊)。
关于它的一个有趣理论在这里。