Wednesday, September 9, 2015

Google Java Style



https://google.github.io/styleguide/javaguide.html
Every constant is a static final field, but not all static final fields are constants. Before choosing constant case, consider whether the field really feels like a constant. For example, if any of that instance's observable state can change, it is almost certainly not a constant. Merely intending to never mutate the object is generally not enough.
static final Logger logger = Logger.getLogger(MyClass.getName());

Projects are free to choose a column limit of either 80 or 100 characters.

Block indentation: +2 spaces

Indent continuation lines at least +4 spaces
One variable per declaration 
Every variable declaration (field or local) declares only one variable: declarations such as int a, b; are not used.
local variables are declared close to the point they are first used (within reason), to minimize their scope. Local variable declarations typically have initializers, or are initialized immediately after declaration.
Fall-through: commented 
Within a switch block, each statement group either terminates abruptly (with a breakcontinuereturn or thrown exception), or is marked with a comment to indicate that execution will or might continue into the next statement group. Any comment that communicates the idea of fall-through is sufficient (typically // fall through). This special comment is not required in the last statement group of the switch block.
The default case is present 
Each switch statement includes a default statement group, even if it contains no code.
In Google Style special prefixes or suffixes, like those seen in the examples name_mNames_name and kName, are not used.

Package names are all lowercase, with consecutive words simply concatenated together (no underscores). For example, com.example.deepspace, notcom.example.deepSpace or com.example.deep_space.

Test classes are named starting with the name of the class they are testing, and ending with Test. For example, HashTest orHashIntegrationTest.

Underscores may appear in JUnit test method names to separate logical components of the name. One typical pattern istest<MethodUnderTest>_<state>, for example testPop_emptyStack. There is no One Correct Way to name test methods.

However, one-character names should be avoided, except for temporary and looping variables.

Each type variable is named in one of two styles:
  • A single capital letter, optionally followed by a single numeral (such as ETXT2)
  • A name in the form used for classes (see Section 5.2.2, Class names), followed by the capital letter T (examples: RequestTFooBarT).
  1. Now lowercase everything (including acronyms), then uppercase only the first character of:
    • ... each word, to yield upper camel case, or
    • ... each word except the first, to yield lower camel case
  2. Finally, join all the words into a single identifier.
Prose formCorrectIncorrect
"XML HTTP request"XmlHttpRequestXMLHTTPRequest
"new customer ID"newCustomerIdnewCustomerID
"inner stopwatch"innerStopwatchinnerStopWatch
"supports IPv6 on iOS?"supportsIpv6OnIossupportsIPv6OnIOS
"YouTube importer"YouTubeImporter
YoutubeImporter*

@Override: always used

Caught exceptions: not ignored

Exception: In tests, a caught exception may be ignored without comment if it is named expected. The following is a very common idiom for ensuring that the method under test does throw an exception of the expected type, so a comment is unnecessary here.

Static members: qualified using class 

When a reference to a static class member must be qualified, it is qualified with that class's name, not with a reference or expression of that class's type.

Finalizers: not used 

It is extremely rare to override Object.finalize.
http://www.hawstein.com/posts/google-java-style.html
https://www.ibm.com/developerworks/cn/java/deconding-code-specification-part-1/index.html
阿里强制规定代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。

Oracle 官网建议不要使用$或者_开始变量命名,并且建议在命名中完全不要使用"$"字符,原文是"The convention,however,is to always begin your variable names with a letter,not '$' or '_'"。对于这一条,腾讯的看法是一样的,百度认为虽然类名可以支持使用"$"符号,但只在系统生成中使用(如匿名类、代理类),编码不能使用。
这类问题在 StackOverFlow 上有很多人提出,主流意见为人不需要过多关注,只需要关注原先的代码是否存在"_",如果存在就继续保留,如果不存在则尽量避免使用。也有一位提出尽量不适用"_"的原因是低分辨率的显示器,肉眼很难区分"_"(一个下划线)和"__"(两个下划线)。
阿里强制规定抽象类命名使用 Abstratc 或 Base 开头。
Stackoverflow 上对于这个问题的解释是,由于这些类不会被使用,一定会由其他的类继承并实现内部细节,所以需要明白地告诉读者这是一个抽象类,那以 Abstract 开头比较合适。
Joshua Bloch的理解是支持以 Abstract 开头。我的理解是不要以 Base 开头命名,因为实际的基类也以 Base 开头居多,这样意义有多样性,不够直观。

避免魔法值的使用

int priceTable[] = new int[16];//这样定义错误;这个 16 究竟代表什么?
正确的定义方式是这样的:
static final int PRICE_TABLE_MAX = 16; //这样定义正确,通过使用完整英语单词的常量名明确定义
int price Table[] = new int[PRICE_TABLE_MAX];
魔法值会让代码的可读性大大降低,而且如果同样的数值多次出现时,容易出现不清楚这些数值是否代表同样的含义。另一方面,如果本来应该使用相同的数值,一旦用错,也难以发现。因此可以采用以下两点,极力避免使用魔法数值。
阿里推荐如果变量值仅在一个范围内变化,且带有名称之外的延伸属性,定义为枚举类。下面这个正例中的数字就是延伸信息,表示星期几。正例如清单 6 所示。
清单 6 正例

1
public Enum {MONDAY(1),TUESDAY(2),WEDNESDAY(3),THURSDAY(4),FRIDAY(5),SATURDAY(6),SUNDAY(7);}

我的理解
对于固定并且编译时对象,如 Status、Type 等,应该采用 enum 而非自定义常量实现,enum 的好处是类型更清楚,不会再编译时混淆。这是一个建议性的试用推荐,枚举可以让开发者在 IDE 下使用更方便,也更安全。另外就是枚举类型是一种具有特殊约束的类类型,这些约束的存在使得枚举类本身更加简洁、安全、便捷。
阿里强制规定单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
1. 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
2. 运算符与下文一起换行。
3. 方法调用的点符号与下文一起换行。
4. 方法调用时,多个参数,需要换行时,在逗号后进行。
5. 在括号前不要换行,见反例。
(提倡同学们尽量不用可变参数编程)。
我的理解
我们先来了解可变参数的使用方式:
1. 在方法中定义可变参数后,我们可以像操作数组一样操作该参数。
2. 如果该方法除了可变参数还有其他的参数,可变参数必须放到最后。
3. 拥有可变参数的方法可以被重载,在被调用时,如果能匹配到参数定长的方法则优先调用参数定长的方法。
4. 可变参数可以兼容数组参数,但数组参数暂时无法兼容可变参数。
至于为什么可变参数需要被放在最后一个,这是因为参数个数不定,所以当其后还有相同类型参数时,编译器无法区分传入的参数属于前一个可变参数还是后边的参数,所以只能让可变参数位于最后一项。
可变参数编程有一些好处,例如反射、过程建设、格式化等。对于阿里同学提出的尽量不使用可变参数编程,我猜测的原因是不太可控,比如 Java8 推出 Lambda 表达式之后,可变参数编程遇到了实际的实现困难。
public class MySingleton {
    //使用 volatile 关键字保其可见性
    volatile private static MySingleton instance = null;
    private MySingleton(){}
    public static MySingleton getInstance() {
        try {
            if(instance != null){//懒汉式
        }else{
            //创建实例之前可能会有一些准备性的耗时工作 
            Thread.sleep(300);
            synchronized (MySingleton.class) {
            if(instance == null){//二次检查 
            instance = new MySingleton();
        }
        }
        }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    return instance;
    }
}

public class MySingleton {         
    //内部类
    private static class MySingletonHandler{
        private static MySingleton instance = new MySingleton();
    }
    private MySingleton(){}
    public static MySingleton getInstance() {
        return MySingletonHandler.instance;
    }
}
枚举 enum 和静态代码块的特性相似,在使用枚举时,构造方法会被自动调用,利用这一特性也可以实现单例。

Switch 语句的使用

阿里强制规定在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。
反例:直接使用 toArray 暂时无参方法存在问题,此方法返回值只能是 Object[]类,若强转其他类型数组将出现 ClassCastException 错误。

https://www.ibm.com/developerworks/cn/java/deconding-code-specification-part-2/index.html

不要捕获 RuntimeException

阿里强制规定 Java 类库中的 RuntimeException 可以通过预先检查进行规避,而不应该通过 catch 来处理,例如 IndexOutOfBoundsException、NullPointerException 等。

高并发服务器 time_wait
阿里推荐高并发服务器建议调小 TCP 协议的 time_wait 超时时间。
说明:操作系统默认 240 秒后才会关闭处于 time_wait 状态的连接,在高并发访问下,服务器端会因为处于 time_wait 的连接数太多,可能无法建立新的连接,所以需要在服务器上调小此等待值。
正例:在 Linux 服务器上通过变更/etc/sysctl.conf 文件去修改该缺省值(秒):net.ipv4.tcp_fin_timeout=30
我的理解
服务器在处理完客户端的连接后,主动关闭,就会有 time_wait 状态。TCP 连接是双向的,所以在关闭连接的时候,两个方向各自都需要关闭。先发 FIN 包的一方执行的是主动关闭,后发 FIN 包的一方执行的是被动关闭。主动关闭的一方会进入 time_wait 状态,并且在此状态停留两倍的 MSL 时长。
主动关闭的一方收到被动关闭的一方发出的 FIN 包后,回应 ACK 包,同时进入 time_wait 状态,但是因为网络原因,主动关闭的一方发送的这个 ACK 包很可能延迟,从而触发被动连接一方重传 FIN 包。极端情况下,这一去一回就是两倍的 MSL 时长。如果主动关闭的一方跳过 time_wait 直接进入 closed,或者在 time_wait 停留的时长不足两倍的 MSL,那么当被动关闭的一方早于先发出的延迟包达到后,就可能出现类似下面的问题:
1. 旧的 TCP 连接已经不存在了,系统此时只能返回 RST 包
2. 新的 TCP 连接被建立起来了,延迟包可能干扰新的连接
不管是哪种情况都会让 TCP 不再可靠,所以 time_wait 状态有存在的必要性。
修改 net.ipv4.tcp_fin_timeout 也就是修改了 MSL 参数。


Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts