Android Code Style Guidelines for Contributors

VLOOKUP_fixed.py 立即下载

英文原文地址:

https://source.android.com/source/code-style.html#java-language-rules


刚入门在进行软件开发的时候,可能在写code的时候有的亲是随心所欲想怎么写就怎么写,只要功能OK就行,而有的亲呢可能会想我的变量名要怎么见名知意, 我的

code要怎么写才健壮等等,当然我更看好后一种想法的小伙伴了,因为有一个好的代码风格,你写出来的code不光便于你自己理解,同时在团队合作的时候更便于别人

的理解与维护,并且能够体现自身的素养与功底,那么我们就根据android对想要向他们提交patch的代码风格要求来学习一下,同时规范自己的每一行代码吧。


好了,划线进入正题~~

===============================================================================================================================

如下这些规则不是指南也不是建议,而是严格的规定(口气还是满严肃的^V^).。如果想要向android贡献代码,不遵循如下的规则提交将不会被接受。

虽然Android中并非所有存在的代码都遵循了如下这些规则,但是我们要求未来添加的任何新代码必须要遵循这些规则。


先简单列一下本文的目录

Java语言规则

  -不要忽略异常

  -不要捕获通用异常

  -不要使用Finalizer

  -高校imports

Java库规则

Java风格规则

  -使用javadoc标准注释

  -写短方法

  -在标准的位置定义属性(字段)

  -控制变量的有效域

  -将import语句排序

  -用空格进行缩进(即不要用tab)

  -遵循字段命名约定

  -使用标准的Brace风格(条件语句除非在一行否则都需要加上花括号{})

  -控制单行的长度

  -使用标准的java注解

  -把缩写当作一个单词

  -使用TODO注解

  -少加log

  -保持一致性

Java测试代码风格规则

  -遵循测试方法命名约定


 正文内容如下,如果看到上面的目录就能明白,可以不用看详细解说,如果看过详细解释那么目录就可以作为条目温习了


Java语言规则

android遵循标准的java编码规则,另外添加了如下几条规则:

不要忽略异常

有时人们很容易写出像如下这种完全忽略异常的代码

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) { }
}

你必须不要再这么写代码了。也许你会觉得你的代码永远不会遇到这个错误条件或者认为处理这个错误并不重要,像上面该这种

忽略异常的方式会在你的代码里创建一座矿山留给其他人去征服在未来的某一天(相当于给别人埋坑)。你必须按照某种原则处理

你代码里面的所有异常。特定的处理方式根据场景的不同做不同的处理。


每当有人在写一个空的catch语句是都应该有一种毛骨悚然的感觉。虽然肯定有时候这样写确实是对的,但是你至少应该对这样写

有所思考。在java里你无法逃避这种毛骨悚然的感觉。----James Gosling


可以接受的备选方案如下(按照优先级排序):

-将异常抛给你的调用者

void setServerPort(String value) throws NumberFormatException {
    serverPort = Integer.parseInt(value);
}

-抛出适合你的抽象层次的新异常,也即给抛出的异常添加一些你的层次能够知道的信息

void setServerPort(String value) throws ConfigurationException {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new ConfigurationException("Port " + value + " is not valid.");
    }
}

-优雅的处理这个错误并在catch块中给替换一个适当的值

/** Set port. If value is not a valid number, 80 is substituted. */

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        serverPort = 80;  // default port for server 
    }
}

-捕获这个异常并抛出一个运行时异常。注意这是危险的:仅仅在你确定发生这个错误后crash是适当的。

/** Set port. If value is not a valid number, die. */

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new RuntimeException("port " + value " is invalid, ", e);
    }
}

需要注意的是原异常会作为参数传递给RuntimeException的构造函数,如果你的代码必须在Java 1.3版本以下进行编译,

那么你将需要省略掉这个源头异常,也就是这个运行时异常的真正原因。

-最后一招:如果你确定以及肯定你忽略掉这个异常是正确的选择,那么至少你应该在catch语句块上写下为什么要这么做,

或者打印log提醒曾经出现过异常

/** If value is not a valid number, original port number is used. */
void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        // Method is documented to just ignore invalid user input.
        // serverPort will just be unchanged.
    }
}

不要捕获通用异常

有时候为了偷懒人们更愿意用如下方式捕获异常

try {
    someComplicatedIOFunction();        // may throw IOException 
    someComplicatedParsingFunction();   // may throw ParsingException 
    someComplicatedSecurityFunction();  // may throw SecurityException 
    // phew, made it all the way 
} catch (Exception e) {                 // I'll just catch all exceptions 
    handleError();                      // with one generic handler!
}

首先你不应该这么做,几乎在所有场景下这样捕获通用异常或者Throwable都是不恰当的,最好不要是Throwable,因为它包含

错误的异常,也就是Error.java,因为Error也继承自Throwable,这样如果直接捕获Throwable,那么真正的Error也被捕获了。这样

做是相当危险的,这就意味着你永远不期望错误的出现,及时是RuntimeException例如ClassCastException,甚至或不捕获了应用

层级的错误处理。它隐藏了你代码的错误处理性能。这就意味着如果在你调用的代码里面某人添加了新的异常类型,编译器并不

会提醒你有新的异常类型需要做特殊处理。毕竟在大多数情况下并非所有的异常都可以用同样一种方式进行处理。


当然万事无绝对,对于此规则也有一些例外的情况:某些测试代码和你想要捕获所有错误的顶层代码(阻止这些错误显示到UI界面上,

或者为了保证接下来批量的任务可以继续执行下去)。在这种场景下你可以捕获通用异常(Exception)或者Throwable并且恰当的处理。

在做这样的决定前你需要做相当仔细的考虑,虽然你会在catch语句块中添加注解说明在这里做这样的处理是安全的。


捕获通用异常的替换处理方式如下:

-捕获可能会在对应的try语句块中所有异常,每个异常对应一个catch语句块,虽然这样写会略显尴尬,但是还是建议捕获所有的异常,

  注意在catch语句中不要出现太多重复的代码

-重构你的代码使用多个try语句块去实现细粒度更高的错误处理,例如从解析中将IO处理分离出来,在每个场景中将错误分开处理。

-重新抛出这个异常,许多时候有些异常不需要在你这一层来进行处理,那就索性将它继续抛出去


记住:异常是你的朋友!当编译器想你抱怨你没有捕获某一个异常的时候,不要皱眉,要微笑,编译器只是想在编译的时候就告诉你,

你有需要处理的潜在错误,不用到运行时候发现再处理


不要使用Finalizer

Finalizer是一种能够在对象在被垃圾回收机制回收时执行一段代码的方法。

优点:可以方便做清理工作,尤其是外部资源

缺点:Finalizer什么时候会被调用是没有保证的,甚至它是否会被调用也是不确定的。

抉择:我们不使用Finalizer。在大多数场景下,你可以将需要在Finalizer中所做的处理用一个好的异常处理来取代。如果你确实需要使用Finalizer,

你可以定义一个closer方法(或者类似的其它方法)并且在注解中写清楚该方法什么时候需要被调用。具体例子可以参考InputStream类。在这种情

况下在Finalizer中打印提示的log信息是比较恰当的方式但并不是必须的,只要这里打印log不会太频繁以至于淹没整理日志。


高效Imports

当你想用用foo包中的Bar类时,你有如下两种方式可以将它import进来

1.import foo.*;

优点:潜在的减少了import语句的数量

2.import foo.Bar;

优点:比较清晰的能够知道具体哪个类是需要用到的,对于维护者来说增加了代码的可读性。

抉择:android代码中所有的import都使用后一种方式,但是java标准库(java.util.*, java.io.*, etc)和单元测试代码(junit.framework.*)例外。


java类库规则

在使用android中的java库和工具是有约定的。在某些情况下,在一些重要的途径中约定会有所改变,还有一些旧代码中会使用一些被废弃的模式以及

类库。当在处理这类代码时,允许跟随已存在的代码风格。但当在创建新的组件的时候不要再使用被废弃的库。


Java风格规则

使用javadoc标准注解

 每一个文件的顶部都应该有版权信息语句,然后跟上包命语句,以及一系列的import语句,每一类语句块之间用一个空白行隔开。在这之后就是类或者

接口的声明。在javadoc注解中描述清楚这个类或者接口具体是用来做什么的。参考如下:

/*
 * Copyright (C) 2013 The Android Open Source Project 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package com.android.internal.foo;

import android.os.Blah;
import android.view.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */

public class Foo {
    ...
}

你所写的每一个类或者重要的公开方法都必须用javadoc注解进行注释,至少包含一句用来描述你这个类和方法是用来做什么的。这个语句应该

以第三人称的口吻来描述。

/** Returns the correctly rounded positive square root of a double value. */
static double sqrt(double a) {
    ...
}

或者

/**
 * Constructs a new String by converting the specified array of 
 * bytes using the platform's default character encoding.
 */
public String(byte[] bytes) {
    ...
}

当然,你不必为每一个类似get和set这种并非很重要的方法添加javadoc注释,例如setFoos这样的方法javadoc中都会描述为"set Foos",这就没有必要了。

如果你的方法做了一些很复杂的事情(例如强制约束或者有比较重要的副作用),这样的方法你就必须要加上注解了。也就是如果不是类似属性“Foo”这种

很明显一眼就能看出其表达的意思,那么你就应该要写出具体的注解。


这样每一个你所写的方法,公开或者其它的,都会从javadoc中收益,如果javadoc注解写得很清楚的话,更利于后期自己或其他人的维护。公开方法属于

API的的一部分因此需要javadoc注解的支持。


Android目前并没有指定javadoc注解的风格。但是你应该遵循How to Write Doc Comments for the Javadoc Tool这个链接中的说明来添加。


写短小的方法

在某种程度上这是可行的,方法应该尽量短小并且集中。然而在有些场景下长方法更合适,因此在方法长度上没有硬性的规定。那么如果方法的长度超过了

40行,就因该考虑一下是否能够在不影响方法的架构的基础上将方法分成几个小的方法


将属性字段定义放在标准的位置

属性字段应该定义在文件的顶部,即类的顶部,或者在即将使用这个字段的方法的上面。


限制变量的作用域

本地变量的作用域应该尽量控制在最小的范围内。这样做能够尽量增加你代码的可读性以及可维护性,减少出现错误的可能性。变量的声明尽量在某一范围的

语句块内,这个语句块范围能够尽量小,最好是刚好覆盖所有使用这个变量的语句。


本地变量应该在第一次使用前进行声明,在每个本地变量被声明的附近应该有对其进行初始化的语句。如果在声明时没有足够的信息来对其进行合理的初始化,

那么你应该尽量推迟该变量的初始化指导你能够进行初始化为止。


这个规则的例外是关于try-catch语句块的。如过变量的初始化是依靠需要进行try-catch进行异常检查的方法调用返回的值,那么该变量必须在try语句块中

进行初始化。如果该变量必须会在try语句块外被用到,那么你必须将该变量的声明提出到try语句块外,并给初始化一个不算是很合理的值。

// Instantiate class cl, which represents some sort of Set 
Set s = null;
try {
    s = (Set) cl.newInstance();
} catch(IllegalAccessException e) {
    throw new IllegalArgumentException(cl + " not accessible");
} catch(InstantiationException e) {
    throw new IllegalArgumentException(cl + " not instantiable");
}

// Exercise the set 
s.addAll(Arrays.asList(args));

但是即使在这种情况下,也可以将try-catch封装在方法中来避免,如下所示

Set createSet(Class cl) {
    // Instantiate class cl, which represents some sort of Set 
    try {
        return (Set) cl.newInstance();
    } catch(IllegalAccessException e) {
        throw new IllegalArgumentException(cl + " not accessible");
    } catch(InstantiationException e) {
        throw new IllegalArgumentException(cl + " not instantiable");
    }
}

...

// Exercise the set 
Set s = createSet(cl);
s.addAll(Arrays.asList(args));

循环变量应该被声明在for语句内,除非因此会有编译错误除外:

for语句

 
for (int i = 0; i < n; i++) {
    doSomething(i);
}

foreach语句
 
for (Iterator i = c.iterator(); i.hasNext(); ) {
    doSomethingElse(i.next());
}

import语句排序

import语句的顺序应该按照如下分组进行排列:
1.Android类的import语句
2.第三方类库import语句(com,junit,net,org)
3.java和javax
要完全匹配IDE的设置,import顺序应该是:
-每组import按照英文字母排序,并且大写字母排在小写字母的前面(例如 Z应该排在a的前面)
-在每组import语句之间应该有一个空白行来隔开(android, com, junit, net, org, java, javax)
import的排序原本上是没有风格要求的。这就意味着要么IDE自动导入的时候总是在更改import的顺序,或者
用IDE研发的coder关闭了IDE的自动import管理功能而自己手动进行import的书写。这样做被认为是很糟糕
的。当IDE中java风格被设定的时候,首选风格会影响所有方面。它几乎满足我们“选择一个排序,并保持一致”
的需求。因此我们可以选择一种风格,更新风格指南,使得所选风格遵循import排序的这种规则。我们期望所有
用IDE进行编码的工程师能够在没有其它工程师的努力下遵循这种import排序的模式。

这种风格的选择需要满足如下条件:
-做imports的人想要查看第一个import应该在android的顶部
-做imports的人想要查看最后一个import应该在java的底部
-人类能够很轻松的遵循这种风格
-集成开发环境能够遵循这种风格

static import的使用以及放置的位置稍有争议。有的人认为静态导入应该穿插在其它各组imports中,而有的人认为
应该单独给静态导入分一个组。此外,我们还没确定一种方法使得所有IDE都遵循一种排序方式。

当大多数人都认为import排序是一种很小的事情时,请作出你自己的裁决并保持一致。

用空格进行缩进
我们使用4个空格作为一个缩进块,从来不使用tab进行缩进。当有疑问时,请保持和周围code一致。
我们使用8个空格作为换行的缩进,包括方法调用和变量的赋值,例如:
正确的方式

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);


错误的方式
Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);



遵循字段命名约定
-非公开(non-public)非静态(non-static)的字段名以“m”开头
-静态字段名以“s”开头
-其它字段名以小写字母开头即可
-常量(public static final)字段全部字母大写
例如:
public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}


使用标准花括号风格

用来括住一段代码的花括号不需要另起一行,只需要跟在其前面的一行代码的最后就可以了,例如
class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

我们要求条件语句的内容需要用花括号包起来,除非整个条件语句能够在一行中写下,当然包括条件判断
以及满足该条件需要执行的语句。参考如下几个例子:
合法
if (condition) {
    body(); 
}

合法
if (condition) body();

不合法
if (condition)
    body();  // bad!


限制单行的长度

在你的代码中每一行应该最多有100字符的长度。
这个规则有很多的争议,不过最后的裁决是100字符的长度已经是长度的最大值了,不能超过这个长度了。
例外1:如果在注释中有命令的例子或者url链接长度超过100个字符,为了命令以及url链接的方便复制粘贴
长度可以超过100个字符
例外2:import语句可以不受这个规则的限制,因为毕竟人很少关注这个,而且这样也简化了工具(IDEs)的开发。
使用标准的Java注解
注解应该优先于其它修改针对统一语言元素来讲。简单的修饰注解(例如@Override)应该同其所修饰的语言元素
处于同一行[关于这一条我搜了下android的代码,有的确实遵循了,但是有没有,个人认为还是单起一行比较美
观]。如果需要好几个注解,或者参数注解,那么每个注解应该单独占一行。
有三个在java中预定义的注解在Android中的标准做法如下:
-@Deprecated:此注解必须用在被注解的元素是即将被弃用的,不鼓励再继续使用。当你使用这个注解时同时需
要在该元素上加载@Deprecated的javadoc标签并写明转换的实现方法。另外,需要注意的是即使别标注为
@Deprecated的方法还是应该能够工作的。
如果你在旧的代码中看到有方法被加上了@Deprecated的标签请给它添加上@Deprecated的注解
-@Oevrride:此注解必须被用在子类重写在父类中声明或实现的方法上。
例如,如果你使用了@inheritdocs javadoc标签,并且来自于某一个类(注意是类不是接口),那么与此同时你
就必须给重写的父类方法添加上@Overrride注解
-@SuppressWarnings:此注解应该仅被用在无法消除警告的情况下。如果一个警告通过了“不可能消除”的测试,那么
此注解就必须被使用了,为了确保所有的警告都准确反应出了代码中的问题。
当SuppressWarnings注解是必须的时候,它的前面必须加上一个TODO注释,解释“不能被消除”的情况。这通常是被
鉴定出一个违规类有不太合适的接口。例如:

// TODO: The third-party class com.third.useful.Utility.rotate() needs generics 
@SuppressWarnings("generic-cast")
List<String> blix = Utility.rotate(blax);



当@SuppressWarnings注解是必需的时候,代码应该被重构将被注解的软件元素隔离开来。
将缩写当作单词
在给变量,方法和类命名时将缩略词当作一个单词。这样这些名字可读性就更强了:
Good & Bad Sample
JDK和Android代码库针对缩写处理都非常不一致。因此,实质上也是不可能让你附近的代码都保持一致的,那么硬着头皮将缩写当作
一个单词吧。
使用TODO注释
代码使用TODO注释是一个临时的,短期的解决方法,或者说是足够好但是不完美的方法。
TODO注释应该以TODO全大写字符开头,后面跟上冒号:
这样
// TODO: Remove this code after the UrlTable2 has been checked in.


或者这样
// TODO: Change this to use a flag instead of a constant.


如果你以"在未来某个时间做某事"的形式添加TODO注释,那么你要么需要加上非常具体的日期("Fix by November 2005"),要么写上
非常具体的事件("Remove this code after all production mixers understand protocol V7.")。
保守的添加log
如果当log是必须的时候,如果该log没有保持足够合理以及间接那么它必要会给性能带来显著的负面影响,从而立马丢失了它的有效作用。
Log设备给提供了五种不同级别的log,如下所述:
-ERROR:这个级别的log应该在发生了某些致命的事情时。即某些用户可见的后果,并且不能够恢复如果不通过明确的删除某些数据,卸载
      应用程序,擦出数据分区或者重新刷机(或者更糟糕)这些方式。这个级别的日志是会总被记录的。这些被标记为ERROR的log信息
      将被作为上报到数据统计收集服务器上的候选者。
-WARNING:这个级别的log应该用在发生了严重并且在意料之外的事情时。即某些将会是用户可见的后果但是很可能会被恢复而不会有数
      据丢失由于执行了某些明确的操作,范围从等待或者重启应用程序一直到重新下载应用程序的新版本或者重启设备。这个级别的log也
      是总会被记录的。WARNING级别的log信息也将被考虑是否上报给数据统计收集服务器
-INFORMATIVE:这个级别的log信息应该在需要提示发生某些大多数人比较关心的事情是打印。即当一个解决方案被采用但其极有可能会
      影响比较广,虽然不一定是一个错误。这种状态的log应该被在这个领域具有权威性的模块打印(避免非权威模块的log重复打印),这个级
             别的log也是总会被记录的。
-DEBUG:这个级别的log打印是为了进一步提示在设备上发生了什么事情以便与调查和调试非期望事情发生的原因。你应该只打印需要用来搜集
      足够的信息以确定你的模块都发生了些什么的log内容。如果你的调试log信息占据了整个log日志那么你应该使用详细日志级别VERBOSE。
      这个级别也会被记录,甚至是在发布版本上,并且这个log需要被if (LOCAL_LOG)或者if (LOCAL_LOGD)语句块包围,而LOCAL_LOG[D]
      会被定义在你的类或者子模块中,这样就存在了关闭所有这类log的可能性。因此在If (LOCAL_LOG[D])语句块中不能有代码逻辑相关内容。
      并且所有的字符串拼装也只能在这个语句块中进行。如果将if (LOCAL_LOG[D])语句块提取成一个方法会导致字符串的拼装被提取到这个语
      句块之外的话,是不建议这么做的。
      也许现有代码中还有通过if (localLOGV)这种形式,虽然它的名字不规范,但是也被考虑为可以接受的。
-VERBOSE:这个级别的log应该用于可以打印一切信息。这类log应该仅在调试版本上被记录,并且应该被if(LOCAL_LOGV)语句快包围(或者其它
      等效的方式),因为这样我们才可能在默认的版本上不记录这个类型的log。任何关于这个log的字符串拼装都应该剥离在if (LOCAL_LOGV)
      中,以保证其不会出现在发行(release)版本中。
注意:
-在一个给定的模块中,除了VERBOSE级别的log信息外,一个错误的日志应该尽量只被打印一次:在一个模块的一连串函数调用中,应该仅最内层的
 方法调用应该返回错误,而该函数的调用者应该仅仅打印一些对与分离问题原因有重要作用的log信息。
-在模块链中,除了VERBOSE级别的log信息外,在低层模块中发现了来自于高层模块的无效数据,低层模块应该仅将这种情况打印在DEBUG级别的
  log信息中,并且仅当日志提供了不会另外对调用者有效的信息。具体来讲,没有没有必要给抛Exception的场景(这个exception应该会携带
  所有的有效信息),或者仅有包含一个错误代码的信息的场景打印log。这一点在framework和apllication之间尤其重要,并且这种状况由第三方应用程序
  导致时framework正确的处理方式就是不应该打印高于DEBUG级别的log信息。能够触发INFORMATIVE或者更高级别的log信息打印的场景是仅当一个
  模块或者应用程序发现了自身的错误或者其对应的低层级的错误。
-当在某种情况发生时,有部分log会被打印很多次,那么比较好的做法应该是通过实现某中速率限制的机制来控制相同或者相似的log信息被打印多次,
 以至于淹没整个日志。
-网络连接的断开被认为是普遍并且完全可以预料到的场景,因此不应该随便的打印这种场景发生的log信息。网络连接的断开如果给app带来一定的后果
 那么应该被记录为DEBUG或者VERBOSE级别(完全取决于后果是否足够严重并且足够出乎意料到需要记录在发行版本中)。
-A full filesystem on a filesystem that is accessible to or on behalf of third-party applications should not be logged at a level higher than INFORMATIVE
  真心无力翻译,可能这方面接触得少,搞不明白想表达什么,之后明白了再翻译吧 = =||
-无效数据来自于任何不可信的源头(包括共享存储上的文件,或者来自任何网络的数据)被认为是预料之中的,当数据被发现为无效时(即便如此log也是
 被尽可能限制的)不应该打印高于DEBUG级别的log信息
-请记住当你在给字符串使用+操作符时,会隐式创建一个默认拥有16个字符大小缓冲区的StringBuilder对象以及几个其它的临时字符串对象。即显示创建
 StringBuilder并不会比用+操作符更加高的资源消耗(没准可能会更高效)。与此同时也请记住调用Log.v的代码在发行版本上会被编译并且执行,包括编译
 字符串,即使logs别没有被读取。
-所有是为了给人们阅读以及出现在发行版本上的log日志都应该精炼但不神秘,也就是不要太晦涩难懂,应该能够被人合理的理解。这包括所有高于等于
 DEBUG级别的log
-当可能的时候,log应该保持在一行内如果合理的话。单行的长度应该在80或者100个字符长度以内。当长度超过了130或者160个字符长度(包括tag的长度)
  在可能的情况下应该尽量避免
-用于提示成功的log信息的级别应该不得高于VERBOSE
-临时log为了确认很难复现的问题应该使用DEBUG或者VERBOSE级别,and should be enclosed by if blocks that allow to disable it entirely at compile-time.
  后面这句翻译不动了
-小心通过log发生的安全泄漏。私有信息应该被避免打印。被保护内容的信息毫无疑问必须应该避免打印。尤其是在写framework代码时由于并不容易能够
  知道哪些内容会是私有或者被保护的,所以在写代码的时候更应该注意对安全的考虑
-System.out.println() (或者native代码中的printf() )应该永远不被使用。System.out和System.err会被重定向到/dev/null,所以你的log将不会被打印到能看到的
  地方。然而,所有关于这写调用的字符串创建仍然会被执行。
-日志的黄金规则是你的log可能没有必要将被人的log推出缓存区,就像别人的log可能不会推出你的一样。
保持一致
我们的临别思想:保持一致。当你在编辑代码的时候,花几分钟的时间看看附近的代码,然后决定你的代码风格。如果它们的if语句周围有
间距,那么你也应该这样做。如果它们的注释周围有星号包围,那没你的注释也应该有星号围绕。
这篇代码风格的关键在与能够有通用的编码词汇,这样人们可以专注于你在说什么,而不是你怎么在说。我们在这里介绍了整体风格规则以便
人们能够知道这些词汇。但是本地风格(代码原来的风格)也同样很重要,也许你遵循了此文章所说的规则,但是你修改了一个文件,在里面添
加了打篇幅的不一样风格的代码,这样子完全改变了阅读代码者的节奏,不可取,尽量阻止这样的事情发生。
Java测试风格规则
遵循测试代码命名约定
当给测试方法命名的时候,你可以用下划线来将当前正在测试的内容从具体测试case中分离出来。这个风格能够更便于知道什么内容被测试了。
例如:
For example:


testMethod_specificCase1 testMethod_specificCase2


void testIsDistinguishable_protanopia() {
    ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
    assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
    assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}

D打卡签到,蓝牙中继,广播信号模拟器 模拟WIFI或蓝牙,有如下4种运行模式 1、WIFI模式:指定SSID、BSSID名称等,模拟WIFI,供设备连接。 2、蓝牙静态模式:指定MAC地址,广播固定的RAW数据。 3、蓝牙动态主机模式:扫描周围蓝牙设备,获取指定MAC地址的蓝牙及其RAW数据,实时发送至Cloud云端,可以设定时间段,只在设定的时间段内发送。 4、蓝牙动态从机模式:指定MAC地址,从Cloud云端获取动态主机模式实时上传的该MAC地址的RAW数据,并广播RAW数据。 准备工作: 1、板子:选择ESP32C3或ESP32C3 Supermini 2、nRF Connect手机app:用于扫描获取待模拟蓝牙设备的MAC和RAW数据。 Wifi分析仪或WiFi魔盒手机APP:用于扫描获取待模拟WIFI设备的SSID和BSSID。 3、可使用官方flash_download_tool_3.9.11工具来固件烧录。 使用说明: 上述完成后,设备首次上电,RESET一侧的指示灯会常亮,可以把它理解成电源指示灯; BOOT一侧的灯会亮,该灯常亮,表示设备开启了AP模式,此时设备会发射一个WIFI信号源,名称为ESPWIFI_AP,密码为12345678,手机或电脑连接该WIFI,浏览器输入192.168.4.1,进入设备的配置页面,进行相应的配置,其中动态主机模式和动态从机模式的SSID、Pwd 及要模拟的蓝牙MAC地址。配置完成并保存后,会重启,重启后设备会按照保存的配置运行。若下次要修改设备配置,可以长按BOOT按键,等待BOOT一侧的灯常亮,即进入AP模式,再按照上述流程配置即可。 仅用于蓝牙设备的开发与调试,请勿用于签到等违法违纪用途。 立即下载

相关推荐

YOLO26算法心电图十二导联目标检测+训练好的模型+368张数据集+pyqt可视化界面.zip

附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[导联I(I), 导联II(II), 导联III(III), 胸导联V1(V1), 胸导联V2(V2), 胸导联V3(V3), 胸导联V4(V4), 胸导联V5(V5), 胸导联V6(V6), 加压肢体导联aVF(aVF), 加压肢体导联aVL(aVL), 加压肢体导联aVR(aVR)] · 训练集:313 张 · 验证集:37 张 · 测试集:18 张 · 总计:368 张 该数据集聚焦于临床心电图信号的精准识别与定位,其核心检测目标为标准12导联心电图中的各个独立导联波形区域,涵盖肢体导联(I、II、III)与加压肢体导联(aVR、aVL、aVF),以及胸前导联(V1至V6),适用于心电图自动分析系统中对各导联位置的快速准确标注与分类。数据采集场景真实还原了医院心电图室或急诊监护环境下的标准心电图记录纸,波形清晰、基线稳定,具有高度临床参考价值。... 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 57 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.9708** mAP50-95 | 0.6344 Precision | 0.8990 Recall | 0.9191 train/box_loss | 1.2231 train/cls_loss | 0.9703 val/box_loss | 1.2779 val/cls_loss | 0.... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。

Android开源项目-编码风格规范-Code Style Guidelines for Contributors

Code Style Guidelines for Contributors 版本:Android 4.0 r1 英文原文:http://source.android.com/source/code-style.html 以下规则并非指导或推荐的性质,而是必须遵守的规定。如果不遵守这些规定,Android通常不会接受投稿。 已有的代码未必全部遵守了这些规定,但是新的代码全部都应该遵

蓝斯的专栏 6602

企业级AI助手平台 开箱即用的全栈AI平台,支持多智能体协同、Supervisor模式编排、多种决策模式、RAG技术和流程编排能力 支持多厂商大模型统一接入与管理,安全可控的企业知识库与高精度检索优化

企业级AI应用开发框架,支持多厂商大模型统一接入与管理,安全可控的企业知识库与高精度检索优化能力,提供可视化流程编排、自主决策智能体与多智能体协同调度,兼容主流 Agent Skill 协议,帮助企业与开发者零门槛快速构建安全、高效、可落地的AI智能体应用与行业解决方案。

[Android] Code Style Guidelines for Contributors

from http://source.android.com/source/code-style.htmlCode Style Guidelines for ContributorsThe rules below are not guidelines or recommendations, but strict rules. Contributions to Android generally w

田海立@优快云 6174

Java低代码, 轻量级, 支持国产化 国密 AI大模型MCP服务 商业免费 包括核心模块如:组织机构、角色用户、权限授权、数据权限、内容管理、工作流、Spring Cloud 微服务、AI大模型等

Java低代码, 轻量级, 支持国产化 国密 AI大模型MCP服务 商业免费 Spring Boot, MyBatis, Flowable, TypeScript, Vue, Antdv, 包括核心模块如:组织机构、角色用户、权限授权、数据权限、内容管理、工作流、Spring Cloud 微服务、AI大模型、代码生成器等

文创媒体电商行业智算中心(AIDC)建设规划方案.pptx

文创媒体电商行业智算中心(AIDC)建设规划方案.pptx

Android开源项目-编码风格规范-Code Style Guidelines for Contributors[原创译文]

Code Style Guidelines for Contributors 版本:Android 4.0 r1 英文原文:http://source.android.com/source/code-style.html 以下规则并非指导或推荐的性质,而是必须遵守的规定。如果不遵守这些规定,Android通常不会接受投稿。 已有的代码未必全部遵守了这些规定,但是新的代码全部

houyu_1983的专栏 1396

集团企业数字化转型AI智能体平台规划及场景应用方案.pptx

集团企业数字化转型AI智能体平台规划及场景应用方案.pptx

Code Style Guidelines for Contributors

The First, it cames from Open Source Project . The rules below are not guidelines or recommendations, but strict rules. Contributions to Android generally will not be accepted if they do not adhere ...

weixin_30597269的博客 233

基于动态窗口法DWA的机器人路径规划研究(Matlab代码实现)

内容概要:本文系统研究了基于动态窗口法(DWA)的机器人局部路径规划算法,深入剖析其在动态环境中实现自主避障与实时轨迹优化的核心机制。文章详细阐述了DWA算法的速度空间采样策略、轨迹预测模型、动力学约束处理及多目标代价函数的设计原理,并通过构建完整的Matlab仿真框架验证算法有效性。结合典型场景的仿真实验,展示了机器人在复杂障碍物环境下如何实时生成安全、平滑且符合运动学约束的最优路径,充分体现了DWA在移动机器人导航中的实用性与鲁棒性。; 适合人群:具备机器人运动规划基础知识和Matlab编程能力,从事智能移动机器人、自动驾驶或服务机器人研发的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入理解DWA算法的理论基础与实现细节;②掌握机器人局部路径规划的仿真实现方法;③为实际机器人系统的导航模块开发提供可复用的算法原型与代码参考;④作为进一步研究高级导航算法(如TEB、MPC)的技术基础。; 阅读建议:建议结合提供的Matlab代码逐模块分析与调试,重点关注速度采样、轨迹积分、障碍物距离计算及代价评估等关键环节,通过调整参数在不同地图环境中进行对比实验,以深刻把握算法性能与参数之间的关系,进而提升对实时路径规划系统设计的理解与应用能力。

【轴承故障诊断】用于轴承故障诊断的集中时频分析研究(Matlab代码实现)

内容概要:本文系统研究了用于轴承故障诊断的集中时频分析技术,重点解决了传统时频分析方法在处理非平稳信号时存在的能量分散与分辨率不足等问题。通过引入集中时频分析方法,能够有效聚焦信号能量,精确提取轴承故障特征频率,提升故障识别的准确性与时效性。文章详细阐述了该方法的理论基础,并结合仿真信号与实际实验数据验证其优越性能,同时提供了完整的Matlab代码实现流程,涵盖信号预处理、时频变换、参数优化及结果可视化等环节,便于读者复现与拓展应用。; 适合人群:具备一定信号处理理论基础和Matlab编程能力的研究生、科研人员,以及从事机械设备状态监测、故障诊断与预测性维护工作的工程技术人员。; 使用场景及目标:①应用于电机、风机、齿轮箱等旋转机械的早期轴承故障检测,实现故障预警;②提升工业设备运维系统的智能化水平,支撑预测性维护体系构建;③作为高校或研究机构在信号处理、机械故障诊断等课程中的教学案例与实践素材。; 阅读建议:建议读者结合文中提供的Matlab代码逐段运行与调试,深入理解集中时频分布的生成机制及其关键参数(如核函数选择、平滑窗口大小)对诊断效果的影响,并尝试将其应用于其他类型的机械故障信号分析中,开展对比研究以深化对该方法适用性的认识。

Code Style Guidelines for Contributors (一)

Code Style Guidelines for Contributors 代码提交风格指导(一) 原文链接:http://source.android.com/source/code-style.html 偶然在查看android文档时看到的这篇代码风格指南,索性拿来翻译一下,一则多学习点知识,而来也可锻炼下就已为用的英文,文中翻译不当之处,恳请指正;       以下规则不是选择性的建

小文子的专栏 571

2024 《计算机网络》实验教学指导书.doc

2024 《计算机网络》实验教学指导书.doc

基于MPC的风储联合调频模型研究(Simulink仿真实现)

内容概要:本文系统研究了基于模型预测控制(MPC)的风能与储能系统联合频率调节模型,并通过Simulink工具实现了完整的仿真验证。文章深入剖析了风储联合系统的整体架构设计,详细阐述了MPC控制器的建模原理及其在电网频率调节中的具体应用机制,重点探讨了系统在应对负荷突变与风电功率波动等典型扰动下的动态响应特性与控制性能表现。通过与传统控制策略的仿真实验对比,充分验证了所提出的MPC方法在提升电网频率稳定性、抑制频率偏差方面的显著优越性,并进一步分析了控制器关键参数对系统整体性能的影响规律,为高性能控制策略的设计提供了理论依据。; 适合人群:具备电力系统分析、自动控制理论基础,熟练掌握Simulink/Matlab仿真环境,从事新能源并网、电力系统稳定控制、储能系统集成与优化等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于高比例可再生能源接入背景下电网频率调节的关键技术研究;②为风储联合系统的规划、设计与运行优化提供先进的控制策略参考;③作为模型预测控制在电力系统领域应用的经典教学案例,深化对MPC预测机制、滚动优化与反馈校正等核心原理的理解与实践能力。; 阅读建议:建议读者结合提供的Simulink仿真模型进行同步操作与验证,重点关注MPC控制器的状态空间建模、预测时域设定、代价函数构建及参数整定过程,通过对比不同工况与参数配置下的仿真结果,深入理解风储系统协同调频的作用机理与MPC控制的优势所在。

数据结构与算法——7-2 一元多项式的乘法与加法运算 (20分)

设计函数分别求两个一元多项式的乘积与和。 输入格式: 输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。 输出格式: 输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。 输入样例: 4 3 4 -5 2 6 1 -2 0 3 5 20 -7 4 3 1 输出样例: 15 24 -25 22 30 21 -10 2

qazwsxxxxxasd的博客 1484

Proteus仿真实战:用STM32F103C8T6输入捕获模式精准测量PWM频率(附完整代码)

本文详细解析了如何在Proteus仿真环境中,利用STM32F103C8T6的输入捕获模式精准测量PWM频率。文章从输入捕获的工作原理、Proteus电路搭建、模块化代码实现到调试优化,提供了完整的实战指南和代码示例,帮助开发者深入理解并掌握这一关键技术。

weixin_29158047的博客 257
上一篇: Android IPC 进程间通信实现理解
下一篇: Android Proguard介绍
AnnaLoad
博客等级 码龄17年 7粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值