【Java】优雅代码更需要优雅的写法

本文不谈技术,而是关注Java语言设计层面的语法问题,包括命名规则、不建议的命名方式、注释的使用以及一些不成文的命名规则。作者强调了代码规范的重要性,如驼峰式和帕斯卡命名法的应用,避免使用汉字或拼音命名,以及注释和注解的恰当使用,旨在提高代码的可读性和美观性。

      各位优秀的程序员们,相信你们已经阅读过很多遍JDK的源码以及一些优秀的业务、框架源码了,但是总有一些源码让我等望而却步 ,原因并不是因为代码的难度,而是因为代码的规范程度,好的代码在拥有足够深的技术水平之上肯定会以足够赏心悦目的书写规范来呈现给大家。

    本篇文章不谈技术,浅谈一些Java语言设计层面上的语法问题。

首先介绍几种常见的书写语法:

驼峰式命名法Lower-Camel-Case):(小) 驼峰式命名法是Java推荐的书写语法 要求如果命名字段中有多个单词,首单词的首字母小写,之后的单词首字母大写。

public String lowerCamelCase(){}

 

帕斯卡命名法(Upper Camel Case) : 帕斯卡命名法又称大驼峰命名法,是C#推荐的书写语法,要求命名字段中的所有单词首字母大写,在Java中通常用作类名的书写。

public void UpperCamelCase(){}

匈牙利命名法(Hungarian nomenclature)匈牙利命名法是一名匈牙利程序员发明出的命名法,要求在命名之前通常加入其对应的数值类型。

private String szString;

本文因针对Java语言,故以驼峰式命名法为基准,其他命名法作为掌握即可。

Java语法规范基本按照JDK源码规范书写:

命名规则

名称只能由字母、数字、下划线、$符号组成 且不能以数字开头 ,一般情况下开发者不会特意的去使用美元符或者下划线作为开头字母。

名称不能使用JAVA中的关键字或保留字。Java会将.java文件编译成.class的字节码文件,如果把变量名称设置为Java中的关键字或保留字,会在编译期间将变量名称当成关键字或保留字处理,会产生编译时异常。

 

不建议取用

不建议使用汉字或拼音进行命名。 在实际的开发环境中,一个项目会分配给多个工作组人员共同完成,所以不要采用中文或者拼音混淆的方式进行命名,而且有些工作组内尚有外国友人,一定要用世界通用语言,英语来标准命名,不要采用中文或汉语拼音的书写形式。标准命名也促进了自己的英语学习不是吗?

 

命名规范

      项目名称小写。项目名称小写是为了美观,而且与下一条相辅相成↓

      包名称小写。包名就是一个目录的名字,既要起到名称的作用,又要起到目录的作用,名称告知程序员包的作用,目录告诉程序员这个包的功能,尽量将包的名称起的抽象一些,才能起到包含的作用,如SSM中的包名经常为controller,dao,pojo,service.....而具体每个包下都包含着什么类呢,即使初次看代码的程序员也肯定能猜得到,controller层下肯定都是各种各样的具体的controller类啦~

package com.alibaba.fastjson ->  JSON
                             ->  JSONArray
                             ->  JSONObject

    类名按帕斯卡命名法命名。作为面向对象的编程语言,类的命名要与普通的变量命名做以区分,那么如何做区分呢,便是通过帕斯卡命名法和驼峰式命名法的区别。

 变量名、方法名按驼峰式命名法命名。

 常量名全部大写。在Java的语法中有一类特殊的变量,即常量,那么如何区分变量和常量的区别呢?Java规定,在常量的书写中,要求常量名称全部采用大写字母,如Math类中的常量π的命名


    /**
     * The {@code double} value that is closer than any other to
     * <i>pi</i>, the ratio of the circumference of a circle to its
     * diameter.
     */
    public static final double PI = 3.14159265358979323846;

注释

 Java中的注释主要分为三种:

单行注释,一般用于语句间的注解,针对一些较难理解或者值得注意的语句的提醒,例如ArrayList源码中对于GC处理的注解。

private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

多行注释,一般用于大段篇幅的注解,但是不会记录进Javadoc中。

/*

   Multi-line comment

*/

文档注释,一般用于大段篇幅的注解,会记录进Javadoc中,且可以内嵌HTML标签,再Javadoc中以HTML文档进行展示,例如String类中的value[]注释

/** The value is used for character storage. */
    private final char value[];

注解修饰

注解的存在可以试试代码更加整洁美观,以下为几种常用的注解

@Override:面向对象语言的四大特点,封装继承抽象多态,当类与类之间产生继承关系并要重写其超类方法时,要注明@Override注解

 @Override
    public String toString() {
        return "HelloWorld";
    }
@Deprecated:带有@Deprecated注解的属性或类或方法被标注为弃用,不建议使用,通常源码中,带有@Deprecated注解的类或方法的上方文档注释都写有可以替代的类或方法。例如String类中弃用的构造方法方法String(byte ascii[], int hibyte)。
    @Deprecated
    public String(byte ascii[], int hibyte) {
        this(ascii, hibyte, 0, ascii.length);
    }

@param:@param作用于有参数方法的文档注释中,用于解释传入参数的意义,方便其他开发者进行代码阅读或逻辑开发,一般格式为 @param parameterName  reference

@return: @return作用于有返回值的方法的文档注释中,用于指明返回值的含义,方便其他开发者进行代码阅读或逻辑开发  一般格式为 @return  reference

@see:@see 用于文档注释中,用于指明该方法或类可以参考的对象,@see 后面如果加className表示可以参考className类,如果加#methodName时,则表示可以参考本类中的methodName方法。

一般格式为 @see className

                   @see #methodName

一下为Spring中StringUtils类种hasLength方法的文档注释,其中的还掺杂有html标签和@code等注释,如有兴趣可以自行学习。

	/**
	 * Check that the given {@code CharSequence} is neither {@code null} nor
	 * of length 0.
	 * <p>Note: this method returns {@code true} for a {@code CharSequence}
	 * that purely consists of whitespace.
	 * <p><pre class="code">
	 * StringUtils.hasLength(null) = false
	 * StringUtils.hasLength("") = false
	 * StringUtils.hasLength(" ") = true
	 * StringUtils.hasLength("Hello") = true
	 * </pre>
	 * @param str the {@code CharSequence} to check (may be {@code null})
	 * @return {@code true} if the {@code CharSequence} is not {@code null} and has length
	 * @see #hasText(String)
	 */
	public static boolean hasLength(@Nullable CharSequence str) {
		return (str != null && str.length() > 0);
	}

不成文的命名规则

所谓不成文的命名规则即在遵循Java语法命名规则之上,有着对代码可读性,美观性进行进一步提升命名规则,也体现出一个优秀程序员的自我修养。

       命名要有含义,所谓望文知意。在公司级别项目组中,各部门需要通过git进行代码上的补充和整理,代码命名的整洁可以提高代码的可读性。

      不避讳代码名称长度过长。有很多的程序员经常用一些缩写字母来代替变量或是类的名称,导致了代码的可读性极差,如果程序员的命名是cowal , 无论谁都猜不到是什么意思,这也是为什么JDK源码中要把它命名为CopyOnWriteArrayList(java.util.aoncurrent),源码尚不避讳,程序员又有何理由用缩写呢?

java.util.concurrent.CopyOnWriteArrayList;

接口命名采用形容词:面向接口编程在实战当中很常见,一个接口可以被多个类实现,那么一个接口也就有着众多个类的共同属性,也就是说这个接口的名称属性是所有派生类的共有属性,所以以形容词作为接口的名称再适合不过,比如JDK中的接口名称:

Serializable,Callable,Runnable....

接口内方法不书写public关键字,属性不书写final关键字。很多的程序员,包括一些大牛们都会不经意间在接口中的方法前加上public关键字,其实如果仔细阅读过源码的同学可以注意下,无论是JDK源码还是优秀的框架源码,Interface中的方法都是不带有public关键字的,属性都是不带有final关键字的,看似无关痛痒,却是一个程序员对优雅代码的追求和向往。

使用static静态代码块进行常量获取。大家都知道标注final static的属性为全局类属性,那么在初始化时要注意一下的是,如果静态常量初始化赋值,在属性后直接用等于号赋值即可,如果需要进行换算赋值,推荐使用static静态代码块进行赋值,这样可以区不同种类的分静态常量,可以增强代码的可读性,例如

public final static String string = "Hello world";

public final static size;

static{
   size = string.length();
}

使用static进行静态导入:当一个类中需要多次用到同一个工具类中的静态方法使,要进行static静态导入,这样就不必在使用方法时标注类名称,节约代码空间。例如在一个类中反复用到JDK中的Math类的静态方法时,可以通过静态导入,静态导入只能导入方法,不可导入类,但是可以通过*通配符进行通配导入。一般格式为:import static project.package.class.method;

导入Math类中所有静态方法:

import static java.lang.Math.*;

 

 

文章能够记录点滴,知识无量,我们仍需不断的学习进步,希望各位优秀的程序员们能够写出更加优雅的代码。

-by decmoon

 

### 状态模式在 Java 中的优雅实现 在 Java 中,状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。通过将状态和行为封装在不同的类中,状态模式可以有效地替代大量的条件判断语句(如 `if-else` 或 `switch-case`),从而提升代码的可维护性和可扩展性。 #### 状态接口与实现类 定义一个状态接口 `State`,其中包含与状态相关的行为方法。每个具体状态类(如 `OnState` 和 `OffState`)实现这些方法,并根据当前状态执行不同的逻辑。 ```java public interface State { void switchOn(Switcher context); void switchOff(Switcher context); } ``` 具体状态类示例: ```java public class OnState implements State { @Override public void switchOn(Switcher context) { System.out.println("Already ON"); } @Override public void switchOff(Switcher context) { System.out.println("Switching OFF"); context.setState(new OffState()); } } public class OffState implements State { @Override public void switchOn(Switcher context) { System.out.println("Switching ON"); context.setState(new OnState()); } @Override public void switchOff(Switcher context) { System.out.println("Already OFF"); } } ``` #### 状态持有者(Context) `Switcher` 类作为状态的持有者,维护当前状态,并将操作委托给当前状态对象。这种方式实现了状态行为的动态切换。 ```java public class Switcher { private State state; public Switcher() { this.state = new OffState(); // 初始状态为“关” } public void setState(State state) { this.state = state; } public void switchOn() { state.switchOn(this); } public void switchOff() { state.switchOff(this); } } ``` #### 状态机校验的优雅实现 为了实现状态机的校验功能,可以在状态接口中定义校验方法,并在具体状态类中实现校验逻辑。这样可以确保状态切换时满足特定条件,避免非法状态转换。 ```java public interface State { void switchOn(Switcher context); void switchOff(Switcher context); boolean isValidTransition(Switcher context); } ``` 在具体状态类中添加校验逻辑: ```java public class OnState implements State { @Override public void switchOn(Switcher context) { if (isValidTransition(context)) { System.out.println("Already ON"); } else { System.out.println("Invalid state transition"); } } @Override public void switchOff(Switcher context) { if (isValidTransition(context)) { System.out.println("Switching OFF"); context.setState(new OffState()); } else { System.out.println("Invalid state transition"); } } @Override public boolean isValidTransition(Switcher context) { return context.getState() instanceof OnState; } } ``` #### 状态模式的优势 状态模式通过将状态逻辑从宿主类中抽离出来,使得状态切换加清晰和灵活。这种方式不仅减少了宿主类的复杂度,还提高了代码的可测试性和可扩展性。此外,状态模式支持动态状态切换,适用于复杂的业务逻辑场景[^1]。 ### 示例代码 以下是一个完整的状态模式示例,展示了如何通过状态模式实现状态切换和校验: ```java public interface State { void switchOn(Switcher context); void switchOff(Switcher context); boolean isValidTransition(Switcher context); } public class OnState implements State { @Override public void switchOn(Switcher context) { if (isValidTransition(context)) { System.out.println("Already ON"); } else { System.out.println("Invalid state transition"); } } @Override public void switchOff(Switcher context) { if (isValidTransition(context)) { System.out.println("Switching OFF"); context.setState(new OffState()); } else { System.out.println("Invalid state transition"); } } @Override public boolean isValidTransition(Switcher context) { return context.getState() instanceof OnState; } } public class OffState implements State { @Override public void switchOn(Switcher context) { if (isValidTransition(context)) { System.out.println("Switching ON"); context.setState(new OnState()); } else { System.out.println("Invalid state transition"); } } @Override public void switchOff(Switcher context) { if (isValidTransition(context)) { System.out.println("Already OFF"); } else { System.out.println("Invalid state transition"); } } @Override public boolean isValidTransition(Switcher context) { return context.getState() instanceof OffState; } } public class Switcher { private State state; public Switcher() { this.state = new OffState(); // 初始状态为“关” } public void setState(State state) { this.state = state; } public State getState() { return state; } public void switchOn() { state.switchOn(this); } public void switchOff() { state.switchOff(this); } } public class Main { public static void main(String[] args) { Switcher switcher = new Switcher(); switcher.switchOn(); // Switching ON switcher.switchOn(); // Already ON switcher.switchOff(); // Switching OFF switcher.switchOff(); // Already OFF } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值